├── .fvmrc ├── .gitattributes ├── .github ├── .gitkeep └── workflows │ └── release.yml ├── .gitignore ├── .metadata ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── .zed └── tasks.json ├── LICENSE ├── README.md ├── analysis_options.yaml ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ │ └── io │ │ │ │ └── github │ │ │ │ └── d1y │ │ │ │ └── movie │ │ │ │ └── movie │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable-v21 │ │ │ └── launch_background.xml │ │ │ ├── drawable │ │ │ └── launch_background.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── launcher_icon.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── launcher_icon.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── launcher_icon.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── launcher_icon.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── launcher_icon.png │ │ │ ├── values-night │ │ │ └── styles.xml │ │ │ └── values │ │ │ └── styles.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── assets ├── data │ ├── nsfw.html │ ├── play_tips.txt │ └── source_help.txt ├── images │ ├── error.png │ ├── github_logo.png │ ├── image_faild.png │ └── movie_default.png └── loading.gif ├── design ├── logo.logoist ├── logo_round.png └── readme.md ├── devtools_options.yaml ├── docs ├── PR.md ├── keyboard.md ├── protocol.md ├── start_dev.md ├── 源制作.md └── 解析.md ├── fonts └── .gitkeep ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Podfile ├── Podfile.lock ├── 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-50x50@1x.png │ │ │ ├── Icon-App-50x50@2x.png │ │ │ ├── Icon-App-57x57@1x.png │ │ │ ├── Icon-App-57x57@2x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-72x72@1x.png │ │ │ ├── Icon-App-72x72@2x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ ├── LaunchBackground.imageset │ │ │ ├── Contents.json │ │ │ └── background.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 └── RunnerTests │ └── RunnerTests.swift ├── lib ├── app │ ├── extension.dart │ ├── modules │ │ ├── home │ │ │ ├── bindings │ │ │ │ └── home_binding.dart │ │ │ ├── controllers │ │ │ │ └── home_controller.dart │ │ │ └── views │ │ │ │ ├── cupertino_license.dart │ │ │ │ ├── home_view.dart │ │ │ │ ├── index_home_view.dart │ │ │ │ ├── mirror_check.dart │ │ │ │ ├── mirrortable.dart │ │ │ │ ├── nsfwtable.dart │ │ │ │ ├── parse_vip_manage.dart │ │ │ │ ├── search_view.dart │ │ │ │ ├── settings_view.dart │ │ │ │ └── source_help.dart │ │ └── play │ │ │ ├── bindings │ │ │ └── play_binding.dart │ │ │ ├── controllers │ │ │ └── play_controller.dart │ │ │ └── views │ │ │ ├── chewie_view.dart │ │ │ ├── custom_play.dart │ │ │ ├── play_view.dart │ │ │ └── webview_view.dart │ ├── routes │ │ ├── app_pages.dart │ │ └── app_routes.dart │ ├── shared │ │ ├── bus.dart │ │ ├── mirror_category.dart │ │ └── mirror_status_stack.dart │ └── widget │ │ ├── helper.dart │ │ ├── k_body.dart │ │ ├── k_empty_mirror.dart │ │ ├── k_error_stack.dart │ │ ├── k_pagination.dart │ │ ├── k_tag.dart │ │ ├── k_title_bar.dart │ │ ├── mac.dart │ │ ├── movie_card_item.dart │ │ ├── wechat_popmenu.dart │ │ └── window_appbar.dart ├── builtin │ ├── README.md │ └── maccms │ │ └── maccms.dart ├── isar │ ├── repo.dart │ └── schema │ │ ├── history_schema.dart │ │ ├── mirror_schema.dart │ │ ├── parse_schema.dart │ │ └── settings_schema.dart ├── main.dart ├── shared │ ├── auto_injector.dart │ ├── enum.dart │ └── manage.dart ├── utils │ └── screen_helper.dart └── widget │ ├── flutter_custom_license_page.dart │ └── simple_html │ ├── README.md │ ├── custom_render.dart │ ├── flutter_html.dart │ ├── html_parser.dart │ ├── src │ ├── anchor.dart │ ├── css_parser.dart │ ├── extension.dart │ ├── html_elements.dart │ ├── interactable_element.dart │ ├── layout_element.dart │ ├── replaced_element.dart │ ├── styled_element.dart │ └── utils.dart │ └── style.dart ├── linux ├── .gitignore ├── CMakeLists.txt ├── flutter │ ├── CMakeLists.txt │ ├── generated_plugin_registrant.cc │ ├── generated_plugin_registrant.h │ └── generated_plugins.cmake ├── main.cc ├── my_application.cc └── my_application.h ├── macos ├── .gitignore ├── Flutter │ ├── Flutter-Debug.xcconfig │ ├── Flutter-Release.xcconfig │ └── GeneratedPluginRegistrant.swift ├── Podfile ├── Podfile.lock ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── app_icon_1024.png │ │ │ ├── app_icon_128.png │ │ │ ├── app_icon_16.png │ │ │ ├── app_icon_256.png │ │ │ ├── app_icon_32.png │ │ │ ├── app_icon_512.png │ │ │ └── app_icon_64.png │ ├── Base.lproj │ │ └── MainMenu.xib │ ├── Configs │ │ ├── AppInfo.xcconfig │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── Warnings.xcconfig │ ├── DebugProfile.entitlements │ ├── Info.plist │ ├── MainFlutterWindow.swift │ └── Release.entitlements └── RunnerTests │ └── RunnerTests.swift ├── packages ├── command_palette │ ├── .gitignore │ ├── .metadata │ ├── LICENSE │ ├── README.md │ ├── lib │ │ ├── command_palette.dart │ │ └── src │ │ │ ├── command_palette.dart │ │ │ ├── controller │ │ │ └── command_palette_controller.dart │ │ │ ├── models │ │ │ ├── command_palette_action.dart │ │ │ ├── command_palette_config.dart │ │ │ ├── command_palette_style.dart │ │ │ └── matched_command_palette_action.dart │ │ │ ├── utils │ │ │ └── filter.dart │ │ │ └── widgets │ │ │ ├── command_palette_instructions.dart │ │ │ ├── command_palette_modal.dart │ │ │ ├── command_palette_text_field.dart │ │ │ ├── keyboard_key_icon.dart │ │ │ └── options │ │ │ ├── command_palette_body.dart │ │ │ └── option_highlighter.dart │ ├── pubspec.lock │ └── pubspec.yaml ├── flappy_search_bar_ns │ ├── .gitignore │ ├── .metadata │ ├── LICENSE │ ├── README.md │ ├── lib │ │ ├── flappy_search_bar.dart │ │ ├── scaled_tile.dart │ │ └── search_bar_style.dart │ ├── pubspec.lock │ └── pubspec.yaml ├── flutter_cupertino_settings │ ├── .gitignore │ ├── lib │ │ ├── flutter_cupertino_settings.dart │ │ └── widgets │ │ │ ├── button.dart │ │ │ ├── control.dart │ │ │ ├── description.dart │ │ │ ├── header.dart │ │ │ ├── link.dart │ │ │ ├── secret.dart │ │ │ ├── selection.dart │ │ │ ├── spacer.dart │ │ │ └── widget.dart │ ├── pubspec.yaml │ └── readme.md ├── simple │ ├── lib │ │ ├── intent.dart │ │ ├── utils.dart │ │ └── x.dart │ ├── pubspec.lock │ └── pubspec.yaml └── xi │ ├── .gitignore │ ├── README.md │ ├── lib │ ├── adapters │ │ └── mac_cms.dart │ ├── interface.dart │ ├── models │ │ ├── mac_cms │ │ │ ├── source_data.dart │ │ │ ├── xml_data.dart │ │ │ └── xml_search_data.dart │ │ ├── models.dart │ │ └── spec.dart │ ├── utils │ │ ├── helper.dart │ │ ├── http.dart │ │ ├── json.dart │ │ ├── maccms.dart │ │ ├── path.dart │ │ ├── source.dart │ │ ├── utils.dart │ │ └── xid.dart │ └── xi.dart │ ├── pubspec.yaml │ └── test │ └── xi_test.dart ├── pubspec.lock ├── pubspec.yaml ├── schema ├── README.md ├── assets.json └── v1.json ├── script ├── .gitignore ├── add_builtin_yoyo.mjs ├── bundle-ios ├── bundle-mac ├── ckbot │ ├── .gitignore │ ├── README.md │ ├── go.mod │ ├── go.sum │ ├── main.go │ └── template.html ├── create_schema.mjs ├── draft-release-notes.js ├── fetch_git_info.ps1 ├── fetch_git_info.sh ├── linux_apply_font.py └── patch.d.ts ├── test └── .gitkeep └── windows ├── .gitignore ├── CMakeLists.txt ├── flutter ├── CMakeLists.txt ├── generated_plugin_registrant.cc ├── generated_plugin_registrant.h └── generated_plugins.cmake └── runner ├── CMakeLists.txt ├── Runner.rc ├── flutter_window.cpp ├── flutter_window.h ├── main.cpp ├── resource.h ├── resources └── app_icon.ico ├── runner.exe.manifest ├── utils.cpp ├── utils.h ├── win32_window.cpp └── win32_window.h /.fvmrc: -------------------------------------------------------------------------------- 1 | { 2 | "flutter": "3.22.0" 3 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.html linguist-language=go -------------------------------------------------------------------------------- /.github/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/.github/.gitkeep -------------------------------------------------------------------------------- /.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 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | 48 | cache/ 49 | 50 | json/ 51 | 52 | node_modules/ 53 | 54 | fonts/*.ttf 55 | 56 | *.g.dart 57 | git_info.dart 58 | 59 | # FVM Version Cache 60 | .fvm/ 61 | 62 | flutter_export_environment.sh 63 | Flutter-Generated.xcconfig -------------------------------------------------------------------------------- /.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: "5dcb86f68f239346676ceb1ed1ea385bd215fba1" 8 | channel: "stable" 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 17 | base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 18 | - platform: android 19 | create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 20 | base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 21 | - platform: ios 22 | create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 23 | base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 24 | - platform: linux 25 | create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 26 | base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 27 | - platform: macos 28 | create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 29 | base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 30 | - platform: web 31 | create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 32 | base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 33 | - platform: windows 34 | create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 35 | base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 36 | 37 | # User provided section 38 | 39 | # List of Local paths (relative to this file) that should be 40 | # ignored by the migrate tool. 41 | # 42 | # Files that are not part of the templates will be ignored by default. 43 | unmanaged_files: 44 | - 'lib/main.dart' 45 | - 'ios/Runner.xcodeproj/project.pbxproj' 46 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "movie", 9 | "request": "launch", 10 | "type": "dart", 11 | "program": "lib/main.dart" 12 | }, 13 | { 14 | "name": "movie (profile mode)", 15 | "request": "launch", 16 | "type": "dart", 17 | "flutterMode": "profile" 18 | }, 19 | { 20 | "name": "ck-debug", 21 | "cwd": "${workspaceFolder}/script/ckbot", 22 | "request": "launch", 23 | "type": "go", 24 | "mode": "auto", 25 | "program": "script/ckbot/main.go", 26 | "env": { 27 | "GITHUB_TOKEN":"大傻春你在干什么" 28 | } 29 | }, 30 | ] 31 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "dart.flutterSdkPath": ".fvm/versions/3.22.0", 3 | "cmake.ignoreCMakeListsMissing": true 4 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "shell", 6 | "label": "fetch git info", 7 | "command": "bash", 8 | "args": [ 9 | "script/fetch_git_info.sh" 10 | ], 11 | "group": { 12 | "kind": "build", 13 | "isDefault": false 14 | } 15 | }, 16 | { 17 | "type": "shell", 18 | "label": "build to macOS and install", 19 | "command": "bash", 20 | "args": [ 21 | "script/bundle-mac" 22 | ], 23 | "group": { 24 | "kind": "build", 25 | "isDefault": true 26 | } 27 | }, 28 | { 29 | "type": "shell", 30 | "label": "build to iOS", 31 | "command": "bash", 32 | "args": [ 33 | "script/bundle-ios" 34 | ], 35 | "group": { 36 | "kind": "build", 37 | "isDefault": true 38 | } 39 | }, 40 | { 41 | "type": "shell", 42 | // flutter_launcher_name 与 flutter_launcher_icons 冲突(需要手动取消注释) 43 | "label": "re-generate flutter app name", 44 | "command": "flutter", 45 | "args": [ 46 | "pub", 47 | "run", 48 | "flutter_launcher_name:main" 49 | ] 50 | }, 51 | { 52 | "type": "shell", 53 | "label": "re-generate flutter app icons", 54 | "command": "flutter", 55 | "args": [ 56 | "pub", 57 | "run", 58 | "flutter_launcher_icons:main" 59 | ] 60 | }, 61 | { 62 | "type": "shell", 63 | "label": "dart format", 64 | "command": "dart", 65 | "args": [ 66 | "format", 67 | "." 68 | ] 69 | } 70 | ] 71 | } -------------------------------------------------------------------------------- /.zed/tasks.json: -------------------------------------------------------------------------------- 1 | // https://zed.dev/docs/tasks 2 | [ 3 | { 4 | "label": "flutter debug macos", 5 | "command": "flutter", 6 | "args": [ "run", "-d", "macos" ], 7 | "use_new_terminal": true, 8 | "allow_concurrent_runs": false, 9 | "reveal": "always" 10 | }, 11 | { 12 | "label": "dart format code", 13 | "command": "dart", 14 | "args": [ "format", "." ], 15 | "use_new_terminal": true, 16 | "allow_concurrent_runs": false, 17 | "reveal": "always" 18 | }, 19 | { 20 | "label": "build to macOS and install", 21 | "command": "bash", 22 | "args": [ "script/bundle-mac" ], 23 | "use_new_terminal": true, 24 | "allow_concurrent_runs": false, 25 | "reveal": "always" 26 | }, 27 | { 28 | "label": "build to iOS", 29 | "command": "bash", 30 | "args": [ "script/bundle-ios" ], 31 | "use_new_terminal": true, 32 | "allow_concurrent_runs": false, 33 | "reveal": "always" 34 | }, 35 | { 36 | "label": "flutter test", 37 | "command": "flutter", 38 | "args": [ "test" ], 39 | "use_new_terminal": true, 40 | "allow_concurrent_runs": false, 41 | "reveal": "always" 42 | } 43 | ] 44 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | linter: 4 | rules: 5 | 6 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. 5 | id "dev.flutter.flutter-gradle-plugin" 6 | } 7 | 8 | def localProperties = new Properties() 9 | def localPropertiesFile = rootProject.file("local.properties") 10 | if (localPropertiesFile.exists()) { 11 | localPropertiesFile.withReader("UTF-8") { reader -> 12 | localProperties.load(reader) 13 | } 14 | } 15 | 16 | def flutterVersionCode = localProperties.getProperty("flutter.versionCode") 17 | if (flutterVersionCode == null) { 18 | flutterVersionCode = "1" 19 | } 20 | 21 | def flutterVersionName = localProperties.getProperty("flutter.versionName") 22 | if (flutterVersionName == null) { 23 | flutterVersionName = "1.0" 24 | } 25 | 26 | android { 27 | namespace = "io.github.d1y.movie.movie" 28 | compileSdk = flutter.compileSdkVersion 29 | ndkVersion = flutter.ndkVersion 30 | 31 | compileOptions { 32 | sourceCompatibility = JavaVersion.VERSION_1_8 33 | targetCompatibility = JavaVersion.VERSION_1_8 34 | } 35 | 36 | defaultConfig { 37 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 38 | applicationId = "io.github.d1y.movie.movie" 39 | // You can update the following values to match your application needs. 40 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. 41 | minSdk = flutter.minSdkVersion 42 | targetSdk = flutter.targetSdkVersion 43 | versionCode = flutterVersionCode.toInteger() 44 | versionName = flutterVersionName 45 | } 46 | 47 | buildTypes { 48 | release { 49 | // TODO: Add your own signing config for the release build. 50 | // Signing with the debug keys for now, so `flutter run --release` works. 51 | signingConfig = signingConfigs.debug 52 | } 53 | } 54 | } 55 | 56 | flutter { 57 | source = "../.." 58 | } 59 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 30 | 34 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 51 | 54 | 55 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/io/github/d1y/movie/movie/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package io.github.d1y.movie.movie 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() 6 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/launcher_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/android/app/src/main/res/mipmap-hdpi/launcher_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/launcher_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/android/app/src/main/res/mipmap-mdpi/launcher_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/launcher_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | rootProject.buildDir = "../build" 9 | subprojects { 10 | project.buildDir = "${rootProject.buildDir}/${project.name}" 11 | } 12 | subprojects { 13 | project.evaluationDependsOn(":app") 14 | } 15 | 16 | tasks.register("clean", Delete) { 17 | delete rootProject.buildDir 18 | } 19 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip 6 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | }() 9 | 10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") 11 | 12 | repositories { 13 | google() 14 | mavenCentral() 15 | gradlePluginPortal() 16 | } 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 21 | id "com.android.application" version "7.3.0" apply false 22 | id "org.jetbrains.kotlin.android" version "1.7.10" apply false 23 | } 24 | 25 | include ":app" 26 | -------------------------------------------------------------------------------- /assets/data/play_tips.txt: -------------------------------------------------------------------------------- 1 | 视频中可能包含广告,请勿相信,避免上当受骗。 2 | 视频中所有的广告与作者无关,如有打扰,可快速跳过!(: -------------------------------------------------------------------------------- /assets/data/source_help.txt: -------------------------------------------------------------------------------- 1 | 自动解析对应网址, 通过换行依次加载 -------------------------------------------------------------------------------- /assets/images/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/assets/images/error.png -------------------------------------------------------------------------------- /assets/images/github_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/assets/images/github_logo.png -------------------------------------------------------------------------------- /assets/images/image_faild.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/assets/images/image_faild.png -------------------------------------------------------------------------------- /assets/images/movie_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/assets/images/movie_default.png -------------------------------------------------------------------------------- /assets/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/assets/loading.gif -------------------------------------------------------------------------------- /design/logo.logoist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/design/logo.logoist -------------------------------------------------------------------------------- /design/logo_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/design/logo_round.png -------------------------------------------------------------------------------- /design/readme.md: -------------------------------------------------------------------------------- 1 | 使用 [logoist 4](https://www.syniumsoftware.com/logoist) 设计 2 | 3 | 来自 iconfont: https://www.iconfont.cn/user/detail?spm=a313x.7781069.0.d214f71f6&uid=585018&nid=xg0OdYSjt7Fg -------------------------------------------------------------------------------- /devtools_options.yaml: -------------------------------------------------------------------------------- 1 | description: This file stores settings for Dart & Flutter DevTools. 2 | documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states 3 | extensions: 4 | -------------------------------------------------------------------------------- /docs/PR.md: -------------------------------------------------------------------------------- 1 | # changelog 2 | 3 | 请在必要的 commit 内编写 changelog, 参照格式: 4 | 5 | ```sh 6 | fix: miss codegen type 7 | 8 | This is change 9 | 10 | Release Notes: 11 | - 这修复了 codegen 部分 12 | ``` 13 | 14 | 对应的也可以添加 tag 也可以传递 -m 15 | 16 | ```sh 17 | git tag v1.0 -m "好雨知时节" 18 | ``` -------------------------------------------------------------------------------- /docs/keyboard.md: -------------------------------------------------------------------------------- 1 | # 键盘快捷键 2 | 3 | ## 首页 4 | 5 | - `cmd + k`: 显示命令 6 | - `cmd + [`: 切换上一个 category 7 | - `cmd + ]`: 切换下一个 category 8 | - `cmd + shift + [`: 切换上一个 tabbar 9 | - `cmd + shift + ]`: 切换下一个 tabbar 10 | - `ctrl + p`: 向上滚动 11 | - `ctrl + n`: 向下滚动 12 | - `ctrl + k`: 向上滚动 13 | - `ctrl + j`: 向下滚动 14 | 15 | ## 详情 16 | 17 | - `esc`: 返回到首页 18 | - `enter`: 如果只有一个播放列表, 就直接播放 -------------------------------------------------------------------------------- /docs/protocol.md: -------------------------------------------------------------------------------- 1 | # 示例 2 | 3 | - `yoyo://import` 4 | - 添加单个源: `yoyo://import?name=卧龙&url=https://collect.wolongzyw.com/api.php/provide/vod/at/json&nsfw=false` 5 | - `yoyo://sub` 6 | - 支持订阅源: `yoyo://sub?url=https://cdn.jsdelivr.net/gh/waifu-project/v1@latest/yoyo.json` 7 | - `yoyo://jiexi` 8 | - 支持导入解析链接: `yoyo://jiexi?name=云解析&url=https://yparse.ik9.cc/index.php?url=` 9 | - `yoyo://reset` 10 | - 清除缓存(重置) 11 | - `yoyo://nsfw` 12 | - 开/关 nsfw: `yoyo://nsfw?enable=1` -------------------------------------------------------------------------------- /docs/start_dev.md: -------------------------------------------------------------------------------- 1 | # Re: 环境安装 2 | 下载并安装 `Flutter SDK`, 国内用户请去: https://flutter.cn/ 3 | 4 | > 为避免版本问题, 请下载 (3.22.0) 版本 :) 5 | 6 | 建议国内用户设置这两个环境变量 7 | 8 | ```sh 9 | export FLUTTER_STORAGE_BASE_URL="https://mirrors.tuna.tsinghua.edu.cn/flutter" 10 | export PUB_HOSTED_URL="https://mirrors.tuna.tsinghua.edu.cn/dart-pub" 11 | ``` 12 | 13 | 之后 14 | 15 | ```sh 16 | git clone https://github.com/waifu-project/movie 17 | cd movie 18 | bash script/fetch_git_info.sh 19 | flutter pub get . 20 | flutter pub run build_runner build 21 | flutter run 22 | ``` 23 | 24 | # PR: 贡献源(代码) 25 | 26 | > 要制作源的话请先右转看看[源制作](./源制作.md) -------------------------------------------------------------------------------- /docs/源制作.md: -------------------------------------------------------------------------------- 1 | # 制作规则 2 | 3 | `YY`实现了通用的制作规则如下 4 | 5 | ```jsonc 6 | { 7 | "name": "小不点の资源库", // 名称 8 | "logo": "", // 图标 9 | "desc": "", // 介绍 10 | "nsfw": true, // ******** 11 | "api": { 12 | "root": "http://baidu.com", // 域名 13 | "path": "/xx/xx.php" // api 路径 14 | } 15 | } 16 | ``` 17 | 18 | 理论上来说支持 `ZY-Player` 的源 19 | 20 | 去网上搜索 `资源采集站` 会找到: https://14ysdg.com/archives/82 21 | 22 | 找到这种类型网址: http://help.apibdzy.com 23 | 24 | ![WX20211115-163850.png](https://i.loli.net/2021/11/15/AwfBn2yzMRXdTm6.png) 25 | 26 | 访问该接口查看源码, 注意如果返回的是 `xml` 就对了 :) 27 | 28 | ![WX20211115-164255.png](https://i.loli.net/2021/11/15/j6UEP7AnIwJMV5Y.png) 29 | 30 | 然后依葫芦画瓢编写一个配置文件 31 | 32 | ```json 33 | [ 34 | { 35 | "name": "百度资源", 36 | "logo": "", 37 | "desc": "", 38 | "nsfw": false, 39 | "api": { 40 | "root": " https://cj.apibdzy.com", 41 | "path": "/inc/api.php" 42 | } 43 | } 44 | ] 45 | ``` 46 | 47 | 然后上传到一个可访问的静态资源网站, 然后将网址添加到视频源管理里添加就可以了 -------------------------------------------------------------------------------- /docs/解析.md: -------------------------------------------------------------------------------- 1 | # 基础使用 2 | 3 | 现在支持解析 `爱奇艺`/`优酷` 等视频了, 该功能是为了解决这些官方站点不能播放(vip/广告??)的问题 4 | 5 | 基本上在 `设置->解析源管理` 添加接口, 当播放时检测到官方站点就会走解析 6 | 7 | ![](https://files.catbox.moe/sh6i9k.gif) 8 | 9 | # 源制作 10 | 11 | 比如说去Google搜索一下: `vip视频解析` 就有一大堆, 不过我建议去油猴脚本市场选中 [`iqiyi.com`](https://greasyfork.org/zh-CN/scripts/by-site/iqiyi.com) 站点搜索, 这时候就会出现一些脚本, 脚本里就有线路 12 | 13 | # 导入 14 | 15 | 导入只支持 `json` 文件, 支持数组/对象, 格式: 16 | 17 | ```json 18 | { 19 | "name": "白嫖线路", 20 | "url": "https://baidu.com" 21 | } 22 | ``` -------------------------------------------------------------------------------- /fonts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/fonts/.gitkeep -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | platform :ios, '14.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | end 36 | 37 | post_install do |installer| 38 | installer.pods_project.targets.each do |target| 39 | flutter_additional_ios_build_settings(target) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /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 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /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/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/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/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/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/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/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/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/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/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/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/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/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/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/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/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/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/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/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/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/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/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/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/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/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/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "background.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "LaunchImage.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "LaunchImage@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "LaunchImage@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/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 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /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 | yoyo 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 | CFBundleURLTypes 30 | 31 | 32 | CFBundleTypeRole 33 | Editor 34 | CFBundleURLName 35 | 36 | CFBundleURLSchemes 37 | 38 | yoyo 39 | 40 | 41 | 42 | UISupportedInterfaceOrientations 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | UISupportedInterfaceOrientations~ipad 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationPortraitUpsideDown 52 | UIInterfaceOrientationLandscapeLeft 53 | UIInterfaceOrientationLandscapeRight 54 | 55 | UIViewControllerBasedStatusBarAppearance 56 | 57 | UIStatusBarHidden 58 | 59 | CADisableMinimumFrameDurationOnPhone 60 | 61 | UIApplicationSupportsIndirectInputEvents 62 | 63 | CADisableMinimumFrameDurationOnPhone 64 | 65 | 66 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /lib/app/extension.dart: -------------------------------------------------------------------------------- 1 | import 'package:isar/isar.dart'; 2 | import 'package:movie/isar/repo.dart'; 3 | import 'package:movie/isar/schema/history_schema.dart'; 4 | import 'package:movie/isar/schema/mirror_schema.dart'; 5 | import 'package:movie/isar/schema/parse_schema.dart'; 6 | import 'package:movie/isar/schema/settings_schema.dart'; 7 | import 'package:movie/shared/enum.dart'; 8 | import 'package:url_launcher/url_launcher_string.dart'; 9 | 10 | /// remove this(mixin object 杀伤力太大) 11 | extension ISettingMixin on Object { 12 | IsarCollection get settingAs => IsarRepository().settingAs; 13 | SettingsIsarModel get settingAsValue => IsarRepository().settingsSingleModel; 14 | 15 | IsarCollection get historyAs => 16 | IsarRepository().isar.historyIsarModels; 17 | 18 | IsarCollection get parseAs => 19 | IsarRepository().isar.parseIsarModels; 20 | 21 | IsarCollection get mirrorAs => 22 | IsarRepository().isar.mirrorIsarModels; 23 | 24 | Isar get isarInstance => IsarRepository().isar; 25 | 26 | T getSettingAsKeyIdent(SettingsAllKey key) { 27 | return getSettingAsKey(key) as T; 28 | } 29 | 30 | /// the code is shit|_・) 31 | /// 32 | /// disgustingε(┬┬﹏┬┬)3 33 | /// 34 | /// (っ ̯ -。) 35 | getSettingAsKey(SettingsAllKey key) { 36 | var curr = settingAsValue; 37 | if (key == SettingsAllKey.themeMode) { 38 | return curr.themeMode; 39 | } else if (key == SettingsAllKey.iosCanBeUseSystemBrowser) { 40 | return curr.iosCanBeUseSystemBrowser; 41 | } else if (key == SettingsAllKey.macosPlayUseIINA) { 42 | return curr.macosPlayUseIINA; 43 | } else if (key == SettingsAllKey.isNsfw) { 44 | return curr.isNSFW; 45 | } else if (key == SettingsAllKey.mirrorIndex) { 46 | return curr.mirrorIndex; 47 | } else if (key == SettingsAllKey.mirrorTextarea) { 48 | return curr.mirrorTextarea; 49 | } else if (key == SettingsAllKey.showPlayTips) { 50 | return curr.showPlayTips; 51 | } else if (key == SettingsAllKey.webviewPlayType) { 52 | return curr.webviewPlayType; 53 | } 54 | return curr.id; 55 | } 56 | 57 | /// the code is shit|_・) 58 | /// 59 | /// disgustingε(┬┬﹏┬┬)3 60 | /// 61 | /// (っ ̯ -。) 62 | updateSetting(SettingsAllKey key, dynamic value) { 63 | var curr = settingAsValue; 64 | if (key == SettingsAllKey.themeMode) { 65 | curr.themeMode = value; 66 | } else if (key == SettingsAllKey.iosCanBeUseSystemBrowser) { 67 | curr.iosCanBeUseSystemBrowser = value; 68 | } else if (key == SettingsAllKey.macosPlayUseIINA) { 69 | curr.macosPlayUseIINA = value; 70 | } else if (key == SettingsAllKey.isNsfw) { 71 | curr.isNSFW = value; 72 | } else if (key == SettingsAllKey.mirrorIndex) { 73 | curr.mirrorIndex = value; 74 | } else if (key == SettingsAllKey.mirrorTextarea) { 75 | curr.mirrorTextarea = value; 76 | } else if (key == SettingsAllKey.showPlayTips) { 77 | curr.showPlayTips = value; 78 | } else if (key == SettingsAllKey.webviewPlayType) { 79 | curr.webviewPlayType = value; 80 | } else { 81 | return; 82 | } 83 | IsarRepository().isar.writeTxnSync(() { 84 | settingAs.putSync(curr); 85 | }); 86 | } 87 | } 88 | 89 | extension Mixxxx on String { 90 | openURL() async { 91 | await canLaunchUrlString(this) 92 | ? await launchUrlString(this) 93 | : throw 'Could not launch $this'; 94 | } 95 | 96 | openToIINA() async { 97 | return 'iina://weblink?url=$this&new_window=1'.openURL(); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /lib/app/modules/home/bindings/home_binding.dart: -------------------------------------------------------------------------------- 1 | import 'package:get/get.dart'; 2 | 3 | import '../controllers/home_controller.dart'; 4 | 5 | class HomeBinding extends Bindings { 6 | @override 7 | void dependencies() { 8 | Get.lazyPut( 9 | () => HomeController(), 10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/app/modules/play/bindings/play_binding.dart: -------------------------------------------------------------------------------- 1 | import 'package:get/get.dart'; 2 | 3 | import '../controllers/play_controller.dart'; 4 | 5 | class PlayBinding extends Bindings { 6 | @override 7 | void dependencies() { 8 | Get.lazyPut( 9 | () => PlayController(), 10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/app/modules/play/views/webview_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'package:get/get.dart'; 4 | import 'package:movie/utils/screen_helper.dart'; 5 | import 'package:wakelock_plus/wakelock_plus.dart'; 6 | import 'package:webview_flutter/webview_flutter.dart'; 7 | 8 | class WebviewView extends StatefulWidget { 9 | const WebviewView({super.key}); 10 | 11 | @override 12 | createState() => _WebviewViewState(); 13 | } 14 | 15 | class _WebviewViewState extends State { 16 | final url = Get.arguments; 17 | 18 | late final WebViewController controller; 19 | 20 | @override 21 | void initState() { 22 | WakelockPlus.enable(); 23 | execScreenDirction(ScreenDirction.x); 24 | init(); 25 | super.initState(); 26 | } 27 | 28 | init() { 29 | // https://github.com/flutter/packages/blob/853c6773177a32be019c55c2ff45c9908196dadd/packages/webview_flutter/webview_flutter/example/lib/simple_example.dart#L27C5-L48C40 30 | controller = WebViewController() 31 | ..setJavaScriptMode(JavaScriptMode.unrestricted) 32 | ..setBackgroundColor(const Color(0x00000000)) 33 | ..loadRequest(Uri.parse(url)); 34 | } 35 | 36 | @override 37 | void dispose() { 38 | super.dispose(); 39 | WakelockPlus.disable(); 40 | execScreenDirction(ScreenDirction.y); 41 | } 42 | 43 | @override 44 | Widget build(BuildContext context) { 45 | return Scaffold( 46 | resizeToAvoidBottomInset: false, 47 | floatingActionButton: Container( 48 | decoration: BoxDecoration( 49 | borderRadius: BorderRadius.circular(10), 50 | color: Colors.black38, 51 | ), 52 | margin: const EdgeInsets.symmetric(vertical: 9), 53 | child: IconButton( 54 | icon: const BackButtonIcon(), 55 | color: Colors.white, 56 | tooltip: MaterialLocalizations.of(context).backButtonTooltip, 57 | onPressed: () { 58 | Navigator.maybePop(context); 59 | }, 60 | ), 61 | ), 62 | floatingActionButtonLocation: FloatingActionButtonLocation.startTop, 63 | body: WebViewWidget(controller: controller), 64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /lib/app/routes/app_pages.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: constant_identifier_names 2 | 3 | import 'package:get/get.dart'; 4 | 5 | import 'package:movie/app/modules/home/bindings/home_binding.dart'; 6 | import 'package:movie/app/modules/home/views/home_view.dart'; 7 | import 'package:movie/app/modules/play/bindings/play_binding.dart'; 8 | import 'package:movie/app/modules/play/views/play_view.dart'; 9 | 10 | part 'app_routes.dart'; 11 | 12 | class AppPages { 13 | AppPages._(); 14 | 15 | static const INITIAL = Routes.HOME; 16 | 17 | static final routes = [ 18 | GetPage( 19 | name: _Paths.HOME, 20 | page: () => HomeView(), 21 | binding: HomeBinding(), 22 | ), 23 | GetPage( 24 | name: _Paths.PLAY, 25 | page: () => const PlayView(), 26 | binding: PlayBinding(), 27 | ), 28 | ]; 29 | } 30 | -------------------------------------------------------------------------------- /lib/app/routes/app_routes.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: constant_identifier_names 2 | 3 | part of 'app_pages.dart'; 4 | // DO NOT EDIT. This is code generated via package:get_cli/get_cli.dart 5 | 6 | abstract class Routes { 7 | Routes._(); 8 | 9 | static const HOME = _Paths.HOME; 10 | static const PLAY = _Paths.PLAY; 11 | } 12 | 13 | abstract class _Paths { 14 | static const HOME = '/home'; 15 | static const PLAY = '/play'; 16 | } 17 | -------------------------------------------------------------------------------- /lib/app/shared/bus.dart: -------------------------------------------------------------------------------- 1 | import 'package:event_bus/event_bus.dart'; 2 | 3 | class SettingEvent { 4 | bool nsfw; 5 | 6 | SettingEvent({this.nsfw = false}); 7 | } 8 | 9 | EventBus $bus = EventBus(); 10 | -------------------------------------------------------------------------------- /lib/app/shared/mirror_category.dart: -------------------------------------------------------------------------------- 1 | import 'package:xi/xi.dart'; 2 | 3 | /// NOTE(d1y): 获取分类最大尝试次数(3次) 4 | const kMirrorCategoryTryCountMax = 3; 5 | 6 | /// 源分类缓存池 7 | /// TODO(d1y): 持久化 8 | class MirrorCategoryPool { 9 | MirrorCategoryPool._internal(); 10 | factory MirrorCategoryPool() => _instance; 11 | static final MirrorCategoryPool _instance = MirrorCategoryPool._internal(); 12 | 13 | Map> stacks = {}; 14 | 15 | //=============================== 16 | /// 标记一个最大数📌的请求分类池 17 | Map fetchCounter = {}; 18 | bool fetchCountAlreadyMax(String key) { 19 | int count = fetchCounter[key] ?? 0; 20 | return count >= kMirrorCategoryTryCountMax; 21 | } 22 | 23 | fetchCountPP(String key) { 24 | int count = fetchCounter[key] ?? 0; 25 | fetchCounter[key] = count + 1; 26 | } 27 | 28 | cleanCounter() { 29 | fetchCounter = {}; 30 | } 31 | //=============================== 32 | 33 | clean() { 34 | stacks = {}; 35 | } 36 | 37 | put(String key, List data) { 38 | stacks[key] = data; 39 | } 40 | 41 | List data(String key) { 42 | return stacks[key] ?? []; 43 | } 44 | 45 | bool has(String key) { 46 | var stack = stacks[key]; 47 | if (stack == null) return false; 48 | return stack.isNotEmpty; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/app/shared/mirror_status_stack.dart: -------------------------------------------------------------------------------- 1 | import 'package:movie/shared/manage.dart'; 2 | import 'package:xi/adapters/mac_cms.dart'; 3 | import 'package:xi/xi.dart'; 4 | import 'package:xi/models/mac_cms/source_data.dart'; 5 | 6 | class MirrorStatusStack { 7 | MirrorStatusStack._internal(); 8 | factory MirrorStatusStack() => _instance; 9 | static final MirrorStatusStack _instance = MirrorStatusStack._internal(); 10 | 11 | final Map _stacks = {}; 12 | 13 | Map get getStacks => _stacks; 14 | 15 | final List _datas = SpiderManage.extend; 16 | 17 | bool? getStack(String stack) { 18 | return _stacks[stack]; 19 | } 20 | 21 | pushStatus(String sourceKey, bool status, {bool canSave = false}) { 22 | _stacks[sourceKey] = status; 23 | if (canSave) { 24 | flash(); 25 | } 26 | } 27 | 28 | flash() { 29 | List data = _datas.map((e) { 30 | bool status = e.meta.status; 31 | String id = e.meta.id; 32 | bool? bStatus = getStack(id); 33 | if (bStatus != null) { 34 | status = bStatus; 35 | } 36 | return SourceJsonData( 37 | name: e.meta.name, 38 | logo: e.meta.logo, 39 | desc: e.meta.desc, 40 | nsfw: e.isNsfw, 41 | api: Api( 42 | root: e.meta.domain, 43 | path: (e as MacCMSSpider).api_path, 44 | ), 45 | id: id, 46 | status: status, 47 | ); 48 | }).toList(); 49 | SpiderManage.mergeSpider(data); 50 | } 51 | 52 | clean() { 53 | _stacks.clear(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /lib/app/widget/helper.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: constant_identifier_names 2 | 3 | import 'package:flutter/cupertino.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | const K_DEFAULT_IMAGE = "assets/images/image_faild.png"; 7 | 8 | Widget kCoverImage = Image.asset( 9 | K_DEFAULT_IMAGE, 10 | width: double.infinity, 11 | fit: BoxFit.cover, 12 | ); 13 | 14 | Widget kErrorImage = ClipRRect( 15 | borderRadius: BorderRadius.circular(8.0), 16 | child: const DecoratedBox( 17 | decoration: BoxDecoration( 18 | color: CupertinoColors.black, 19 | ), 20 | child: Center( 21 | child: Column( 22 | mainAxisSize: MainAxisSize.min, 23 | children: [ 24 | Icon( 25 | Icons.cloud_off, 26 | size: 42, 27 | ), 28 | SizedBox(height: 6), 29 | Text("加载失败") 30 | ], 31 | ), 32 | ), 33 | ), 34 | ); 35 | -------------------------------------------------------------------------------- /lib/app/widget/k_body.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class KBody extends StatelessWidget { 4 | final Widget child; 5 | 6 | const KBody({super.key, required this.child}); 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return Column( 11 | mainAxisAlignment: MainAxisAlignment.start, 12 | crossAxisAlignment: CrossAxisAlignment.start, 13 | children: [ 14 | Expanded(child: child), 15 | const SizedBox(height: 63), 16 | ], 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lib/app/widget/k_empty_mirror.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:get/get.dart'; 3 | import 'package:movie/app/modules/home/controllers/home_controller.dart'; 4 | 5 | class KEmptyMirror extends StatelessWidget { 6 | const KEmptyMirror({ 7 | super.key, 8 | this.width, 9 | required this.cx, 10 | required this.context, 11 | }); 12 | 13 | final double? width; 14 | final HomeController cx; 15 | final BuildContext context; 16 | 17 | double get _width { 18 | if (width == null) { 19 | return 120; 20 | } 21 | return width as double; 22 | } 23 | 24 | TextStyle get _style { 25 | return Theme.of(context) 26 | .textTheme 27 | .titleLarge! 28 | .copyWith(color: context.isDarkMode ? Colors.white : Colors.black); 29 | } 30 | 31 | @override 32 | Widget build(BuildContext context) { 33 | return Center( 34 | child: Column( 35 | mainAxisAlignment: MainAxisAlignment.center, 36 | crossAxisAlignment: CrossAxisAlignment.center, 37 | children: [ 38 | Image.asset( 39 | "assets/images/error.png", 40 | fit: BoxFit.cover, 41 | width: _width, 42 | ), 43 | const SizedBox( 44 | height: 12, 45 | ), 46 | Text( 47 | '无数据源 :(', 48 | style: TextStyle( 49 | color: !context.isDarkMode ? Colors.black : Colors.white, 50 | ), 51 | ), 52 | const SizedBox( 53 | height: 12, 54 | ), 55 | GestureDetector( 56 | child: MouseRegion( 57 | cursor: SystemMouseCursors.click, 58 | child: Text( 59 | "设置 -> 视频源帮助", 60 | style: _style, 61 | ), 62 | ), 63 | onTap: () => cx.changeCurrentBarIndex(2 /*设置*/), 64 | ), 65 | ], 66 | ), 67 | ); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lib/app/widget/k_error_stack.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:get/get.dart'; 3 | 4 | /// 错误栈最大行数 5 | const int kErrorStackMaxLine = 12; 6 | 7 | /// 错误栈展示 `widget` 8 | class KErrorStack extends StatelessWidget { 9 | const KErrorStack({ 10 | super.key, 11 | this.msg = "", 12 | this.maxLine, 13 | }); 14 | 15 | final String msg; 16 | 17 | final int? maxLine; 18 | 19 | int get _maxLine => maxLine ?? kErrorStackMaxLine; 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | if (msg.isEmpty) return const SizedBox.shrink(); 24 | return Card( 25 | color: Colors.transparent, 26 | shadowColor: Colors.transparent, 27 | child: Padding( 28 | padding: EdgeInsets.all(Get.width * .05), 29 | child: Text( 30 | msg, 31 | maxLines: _maxLine, 32 | overflow: TextOverflow.ellipsis, 33 | style: const TextStyle( 34 | fontSize: 12, 35 | fontWeight: FontWeight.w400, 36 | color: Colors.grey, 37 | ), 38 | ), 39 | ), 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/app/widget/k_tag.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// [KTag] 事件触发类型 4 | enum KTagTapEventType { 5 | /// 内容 [content] 6 | content, 7 | 8 | /// 右边 [action] 9 | action, 10 | } 11 | 12 | typedef KTapOnTap = void Function(KTagTapEventType type); 13 | 14 | class KTag extends StatelessWidget { 15 | final EdgeInsetsGeometry margin; 16 | 17 | final EdgeInsetsGeometry padding; 18 | 19 | final Color backgroundColor; 20 | 21 | final Widget child; 22 | 23 | final KTapOnTap onTap; 24 | 25 | const KTag({ 26 | super.key, 27 | this.padding = const EdgeInsets.symmetric( 28 | vertical: 6, 29 | horizontal: 15, 30 | ), 31 | this.margin = const EdgeInsets.fromLTRB(0, 0, 8, 6), 32 | this.backgroundColor = Colors.black26, 33 | required this.child, 34 | required this.onTap, 35 | }); 36 | 37 | @override 38 | Widget build(BuildContext context) { 39 | return Container( 40 | decoration: BoxDecoration( 41 | borderRadius: BorderRadius.circular(6), 42 | color: backgroundColor, 43 | ), 44 | padding: padding, 45 | margin: margin, 46 | child: Row( 47 | mainAxisSize: MainAxisSize.min, 48 | children: [ 49 | InkWell( 50 | onTap: () { 51 | onTap(KTagTapEventType.content); 52 | }, 53 | child: child, 54 | ), 55 | const SizedBox( 56 | width: 3, 57 | ), 58 | InkWell( 59 | onTap: () { 60 | onTap(KTagTapEventType.action); 61 | }, 62 | child: const Icon( 63 | Icons.close, 64 | size: 12, 65 | ), 66 | ), 67 | ], 68 | ), 69 | ); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /lib/app/widget/k_title_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class KTitleBar extends StatelessWidget { 5 | final String title; 6 | 7 | const KTitleBar({super.key, required this.title}); 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | return Container( 12 | padding: const EdgeInsets.symmetric( 13 | horizontal: 12, 14 | vertical: 8, 15 | ), 16 | child: Row( 17 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 18 | crossAxisAlignment: CrossAxisAlignment.end, 19 | children: [ 20 | Column( 21 | crossAxisAlignment: CrossAxisAlignment.start, 22 | children: [ 23 | Text( 24 | title, 25 | style: const TextStyle( 26 | fontSize: 24, 27 | ), 28 | ), 29 | const SizedBox( 30 | height: 8, 31 | ), 32 | Container( 33 | height: 4, 34 | color: Colors.black, 35 | width: 82, 36 | ), 37 | ], 38 | ), 39 | const Row( 40 | children: [ 41 | Text( 42 | "全部", 43 | style: TextStyle( 44 | fontSize: 18, 45 | ), 46 | ), 47 | SizedBox( 48 | width: 4, 49 | ), 50 | Icon(CupertinoIcons.arrow_right_circle), 51 | ], 52 | ) 53 | ], 54 | ), 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /lib/app/widget/movie_card_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:cached_network_image/cached_network_image.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:get/get.dart'; 4 | import 'package:movie/app/widget/helper.dart'; 5 | 6 | class MovieCardItem extends StatefulWidget { 7 | final String imageUrl; 8 | 9 | final String title; 10 | 11 | final VoidCallback onTap; 12 | 13 | const MovieCardItem({ 14 | super.key, 15 | required this.imageUrl, 16 | required this.title, 17 | required this.onTap, 18 | }); 19 | 20 | @override 21 | createState() => _MovieCardItemState(); 22 | } 23 | 24 | class _MovieCardItemState extends State { 25 | bool isHovered = false; 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | return InkWell( 30 | onTap: widget.onTap, 31 | mouseCursor: SystemMouseCursors.click, 32 | child: Container( 33 | width: double.infinity, 34 | padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 3), 35 | child: Column( 36 | crossAxisAlignment: CrossAxisAlignment.start, 37 | children: [ 38 | Expanded( 39 | child: ClipRRect( 40 | borderRadius: BorderRadius.circular(4), 41 | child: CachedNetworkImage( 42 | imageUrl: widget.imageUrl, 43 | width: double.infinity, 44 | fit: BoxFit.fill, 45 | progressIndicatorBuilder: (context, url, progress) => Center( 46 | child: CircularProgressIndicator( 47 | value: progress.progress, 48 | ), 49 | ), 50 | errorWidget: (context, error, stackTrace) => kErrorImage, 51 | ), 52 | ), 53 | ), 54 | const SizedBox(height: 9), 55 | Text( 56 | widget.title, 57 | maxLines: 1, 58 | style: TextStyle( 59 | fontSize: 12, 60 | color: context.isDarkMode ? Colors.white : Colors.black, 61 | ), 62 | overflow: TextOverflow.ellipsis, 63 | ), 64 | ], 65 | ), 66 | ), 67 | ); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lib/builtin/README.md: -------------------------------------------------------------------------------- 1 | # 内建源 -------------------------------------------------------------------------------- /lib/builtin/maccms/maccms.dart: -------------------------------------------------------------------------------- 1 | import 'package:xi/adapters/mac_cms.dart'; 2 | 3 | var list$ = [ 4 | MacCMSSpider( 5 | name: "非凡资源", 6 | logo: "http://ffzy.tv/template/ffzy/static/picture/logo.png", 7 | desc: "高清画质,更新最快,速度最快,永久免费的资源站!", 8 | api_path: "/api.php/provide/vod/at/xml", 9 | root_url: "http://api.ffzyapi.com", 10 | nsfw: false, 11 | id: "ffzy", 12 | status: true, 13 | ) 14 | ]; 15 | -------------------------------------------------------------------------------- /lib/isar/repo.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:isar/isar.dart'; 3 | import 'package:movie/isar/schema/history_schema.dart'; 4 | import 'package:movie/isar/schema/mirror_schema.dart'; 5 | import 'package:movie/isar/schema/parse_schema.dart'; 6 | import 'package:movie/isar/schema/settings_schema.dart'; 7 | import 'package:path_provider/path_provider.dart'; 8 | 9 | // isar auto generated *.g.dart do you want add .gitignore? 10 | // link: https://www.reddit.com/r/FlutterDev/comments/kazxo0/do_you_add_gdart_files_to_gitignore 11 | // I don't like these makefiles (ーー゛) 12 | // the code copy by ChatGPT 13 | 14 | class IsarRepository { 15 | late Isar _isar; 16 | 17 | static final IsarRepository _instance = IsarRepository._internal(); 18 | 19 | factory IsarRepository() { 20 | return _instance; 21 | } 22 | 23 | IsarRepository._internal() { 24 | init(); 25 | } 26 | 27 | safeWrite(VoidCallback fn) { 28 | isar.writeTxnSync(() async => fn()); 29 | } 30 | 31 | safeRead(VoidCallback fn) { 32 | isar.txn(() async => fn); 33 | } 34 | 35 | List> get schemas => [ 36 | SettingsIsarModelSchema, 37 | HistoryIsarModelSchema, 38 | ParseIsarModelSchema, 39 | MirrorIsarModelSchema, 40 | ]; 41 | 42 | Future init() async { 43 | final dir = await getApplicationDocumentsDirectory(); 44 | _isar = await Isar.open( 45 | schemas, 46 | directory: dir.path, 47 | maxSizeMiB: 512, 48 | ); 49 | _initDB(_isar); 50 | } 51 | 52 | @Deprecated("调试模式, 后续请删除") 53 | fake(Isar isar) { 54 | isar.writeTxnSync(() { 55 | isar.settingsIsarModels.clearSync(); 56 | }); 57 | } 58 | 59 | _initDB(Isar isar) { 60 | // _fake(isar); 61 | if (isar.settingsIsarModels.countSync() <= 0) { 62 | debugPrint("[logger] 初始化设置"); 63 | var defaultSetting = SettingsIsarModel(); 64 | if (defaultSetting.mirrorTextarea.isEmpty) { 65 | defaultSetting.mirrorTextarea = 66 | "https://cdn.jsdelivr.net/gh/waifu-project/v1@latest/yoyo.json"; 67 | } 68 | isar.writeTxnSync(() { 69 | isar.settingsIsarModels.putSync(defaultSetting); 70 | }); 71 | } 72 | } 73 | 74 | Isar get isar => _isar; 75 | } 76 | 77 | extension IsarRepositoryModelHelp on IsarRepository { 78 | IsarCollection get settingAs => _isar.settingsIsarModels; 79 | 80 | /// use the instance need init!!! 81 | /// maybe get fail(nill) 82 | SettingsIsarModel get settingsSingleModel => settingAs.getSync(1)!; 83 | } 84 | -------------------------------------------------------------------------------- /lib/isar/schema/history_schema.dart: -------------------------------------------------------------------------------- 1 | import 'package:isar/isar.dart'; 2 | 3 | part 'history_schema.g.dart'; 4 | 5 | @Collection() 6 | class HistoryIsarModel { 7 | Id id = Isar.autoIncrement; 8 | 9 | late String content; 10 | 11 | HistoryIsarModel(this.content); 12 | } 13 | -------------------------------------------------------------------------------- /lib/isar/schema/mirror_schema.dart: -------------------------------------------------------------------------------- 1 | import 'package:isar/isar.dart'; 2 | import 'package:movie/shared/enum.dart'; 3 | 4 | part 'mirror_schema.g.dart'; 5 | 6 | @embedded 7 | class MirrorApiIsardModel { 8 | late String root; 9 | late String path; 10 | } 11 | 12 | @collection 13 | class MirrorIsarModel { 14 | MirrorIsarModel({ 15 | required this.api, 16 | required this.name, 17 | required this.logo, 18 | required this.desc, 19 | required this.nsfw, 20 | required this.status, 21 | this.jiexiUrl, 22 | }); 23 | 24 | Id id = Isar.autoIncrement; 25 | 26 | late String name; 27 | String logo = ""; 28 | String desc = ""; 29 | 30 | bool nsfw = false; 31 | 32 | late MirrorApiIsardModel api; 33 | 34 | @Enumerated(EnumType.ordinal) 35 | MirrorStatus status = MirrorStatus.unknow; 36 | 37 | String? jiexiUrl; 38 | } 39 | -------------------------------------------------------------------------------- /lib/isar/schema/parse_schema.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:isar/isar.dart'; 4 | 5 | part 'parse_schema.g.dart'; 6 | 7 | @Collection() 8 | class ParseIsarModel { 9 | Id id = Isar.autoIncrement; 10 | 11 | late String name; 12 | late String url; 13 | 14 | ParseIsarModel(this.name, this.url); 15 | 16 | factory ParseIsarModel.fromJson(Map json) { 17 | return ParseIsarModel(json['name'] ?? "", json['url'] ?? ""); 18 | } 19 | } 20 | 21 | movieParseModelFromJson(String json) { 22 | var map = jsonDecode(json); 23 | var name = map['name'] ?? ""; 24 | var url = map['url'] ?? ""; 25 | return ParseIsarModel(name, url); 26 | } 27 | -------------------------------------------------------------------------------- /lib/isar/schema/settings_schema.dart: -------------------------------------------------------------------------------- 1 | import 'package:isar/isar.dart'; 2 | import 'package:movie/shared/enum.dart'; 3 | import 'package:webplayer_embedded/webplayer_embedded.dart'; 4 | 5 | part 'settings_schema.g.dart'; 6 | 7 | @Collection(inheritance: false) 8 | class SettingsIsarModel { 9 | Id id = Isar.autoIncrement; 10 | 11 | /// 主题 12 | @Enumerated(EnumType.ordinal) 13 | SystemThemeMode themeMode = SystemThemeMode.system; 14 | 15 | /// `ios` 播放视频是否使用默认的系统浏览器 16 | /// 1. 浏览器默认支持: `m3u8` | `mp4` 17 | /// 2. 网页可以直接跳转给浏览器用 18 | /// (所以`ios`默认直接走浏览器岂不美哉?) 19 | bool iosCanBeUseSystemBrowser = true; 20 | 21 | /// macos播放使用 [iina](https://iina.io) 22 | bool macosPlayUseIINA = false; 23 | 24 | bool isNSFW = false; 25 | 26 | /// 当前源 27 | int mirrorIndex = 0; 28 | 29 | String mirrorTextarea = ""; 30 | 31 | /// 显示播放前的提示(告知用户不要相信广告!) 32 | bool showPlayTips = true; 33 | 34 | @Enumerated(EnumType.ordinal) 35 | IWebPlayerEmbeddedType webviewPlayType = IWebPlayerEmbeddedType.p2pHLS; 36 | } 37 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:bitsdojo_window/bitsdojo_window.dart'; 2 | import 'package:flutter/foundation.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_easyloading/flutter_easyloading.dart'; 5 | 6 | import 'package:get/get.dart'; 7 | import 'package:movie/isar/repo.dart'; 8 | import 'package:movie/shared/auto_injector.dart'; 9 | import 'package:protocol_handler/protocol_handler.dart'; 10 | import 'package:window_manager/window_manager.dart'; 11 | import 'package:xi/utils/helper.dart'; 12 | import 'package:xi/utils/http.dart'; 13 | import 'shared/manage.dart'; 14 | import 'package:movie/shared/enum.dart'; 15 | 16 | import 'app/routes/app_pages.dart'; 17 | 18 | const kStandWenKaiFontName = "LXGW WenKai"; 19 | 20 | ThemeData applyTheme({isDark = true}) { 21 | var theme = isDark ? ThemeData.dark() : ThemeData.light(); 22 | if (GetPlatform.isLinux || kDebugMode) { 23 | theme = theme.copyWith( 24 | textTheme: TextTheme( 25 | bodyMedium: TextStyle( 26 | fontFamily: GetPlatform.isMacOS ? kStandWenKaiFontName : 'LXG', 27 | ), 28 | ), 29 | ); 30 | } 31 | return theme; 32 | } 33 | 34 | /// 返回当前主题 -> [ThemeMode] 35 | Future runBefore() async { 36 | WidgetsFlutterBinding.ensureInitialized(); 37 | // Register a custom protocol 38 | // For macOS platform needs to declare the scheme in ios/Runner/Info.plist 39 | await protocolHandler.register('yoyo'); 40 | if (GetPlatform.isDesktop) await windowManager.ensureInitialized(); 41 | 42 | await XHttp.init(); 43 | await IsarRepository().init(); 44 | await SpiderManage.init(); 45 | registerAutoInjector(); 46 | var currTheme = IsarRepository().settingsSingleModel.themeMode; 47 | Brightness wrapperIfDark = Brightness.light; 48 | if (currTheme.isDark) { 49 | wrapperIfDark = Brightness.dark; 50 | } 51 | if (GetPlatform.isWindows && currTheme.isSytem) { 52 | wrapperIfDark = getWindowsThemeMode(); 53 | } 54 | if (currTheme.isSytem) return ThemeMode.system; 55 | return wrapperIfDark == Brightness.dark ? ThemeMode.dark : ThemeMode.light; 56 | } 57 | 58 | void runAfter() { 59 | if (GetPlatform.isDesktop) { 60 | doWhenWindowReady(() { 61 | const minSize = Size(420, 420); 62 | appWindow.minSize = minSize; 63 | appWindow.alignment = Alignment.center; 64 | appWindow.show(); 65 | }); 66 | } 67 | } 68 | 69 | void main() async { 70 | ThemeMode currentThemeMode = await runBefore(); 71 | runApp( 72 | GetMaterialApp( 73 | title: "yoyo", 74 | scrollBehavior: DragonScrollBehavior(), 75 | initialRoute: AppPages.INITIAL, 76 | getPages: AppPages.routes, 77 | debugShowCheckedModeBanner: false, 78 | themeMode: currentThemeMode, 79 | theme: applyTheme(isDark: false), 80 | darkTheme: applyTheme(), 81 | builder: EasyLoading.init(), 82 | ), 83 | ); 84 | runAfter(); 85 | } 86 | -------------------------------------------------------------------------------- /lib/shared/auto_injector.dart: -------------------------------------------------------------------------------- 1 | import 'package:auto_injector/auto_injector.dart'; 2 | import 'package:webplayer_embedded/webplayer_embedded.dart'; 3 | 4 | final autoInjector = AutoInjector(); 5 | 6 | registerAutoInjector() { 7 | autoInjector.addSingleton(WebPlayerEmbedded.new); 8 | autoInjector.commit(); 9 | } 10 | -------------------------------------------------------------------------------- /lib/shared/enum.dart: -------------------------------------------------------------------------------- 1 | /// 主题(颜色)模式 2 | enum SystemThemeMode { 3 | /// 系统自动 4 | system, 5 | 6 | /// 亮色 7 | light, 8 | 9 | /// 暗色 10 | dark, 11 | } 12 | 13 | extension SystemThemeModeExtension on SystemThemeMode { 14 | bool get isSytem => this == SystemThemeMode.system; 15 | bool get isLight => this == SystemThemeMode.light; 16 | bool get isDark => this == SystemThemeMode.dark; 17 | 18 | String get name { 19 | switch (this) { 20 | case SystemThemeMode.system: 21 | return "系统自动"; 22 | case SystemThemeMode.light: 23 | return "亮色"; 24 | case SystemThemeMode.dark: 25 | return "暗色"; 26 | } 27 | } 28 | } 29 | 30 | enum SettingsAllKey { 31 | themeMode, 32 | iosCanBeUseSystemBrowser, 33 | macosPlayUseIINA, 34 | isNsfw, 35 | mirrorIndex, 36 | mirrorTextarea, 37 | showPlayTips, 38 | webviewPlayType, 39 | } 40 | 41 | /// 镜像源状态 42 | enum MirrorStatus { 43 | /// 可用 44 | available, 45 | 46 | /// 不可用 47 | unavailable, 48 | 49 | /// 未知领域 50 | unknow 51 | } 52 | -------------------------------------------------------------------------------- /lib/utils/screen_helper.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter/services.dart'; 4 | 5 | /// 屏幕方向 6 | enum ScreenDirction { 7 | /// 横屏 8 | x, 9 | 10 | /// 竖屏 11 | y 12 | } 13 | 14 | /// 切换屏幕方向 15 | /// [action] 操作的方向 16 | /// [beforeTime] 在执行该操作时, 猜测若有其他异步操作, 会卡死 `Flutter Engine` 17 | execScreenDirction( 18 | ScreenDirction action, [ 19 | beforeTime = const Duration(seconds: 1), 20 | ]) { 21 | /// 为避免卡死, 在开发模式下不执行操作 22 | if (kReleaseMode) { 23 | Future.delayed(beforeTime, () { 24 | switch (action) { 25 | case ScreenDirction.x: 26 | SystemChrome.setPreferredOrientations([ 27 | DeviceOrientation.landscapeLeft, 28 | DeviceOrientation.landscapeRight 29 | ]); 30 | break; 31 | case ScreenDirction.y: 32 | SystemChrome.setPreferredOrientations( 33 | [DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]); 34 | break; 35 | default: 36 | } 37 | SystemUiOverlayStyle systemUiOverlayStyle = const SystemUiOverlayStyle( 38 | statusBarColor: Colors.transparent, 39 | ); 40 | SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle); 41 | }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/widget/simple_html/README.md: -------------------------------------------------------------------------------- 1 | # simple html 2 | 3 | The package copy by: 4 | https://github.com/Sub6Resources/flutter_html 5 | 6 | I made a custom, not using: 7 | 8 | > Using these tags will have some dependencie... 9 | 10 | - audio 11 | - iframe 12 | - img 13 | - math 14 | - svg 15 | - table 16 | - video -------------------------------------------------------------------------------- /lib/widget/simple_html/src/anchor.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | import 'styled_element.dart'; 4 | 5 | class AnchorKey extends GlobalKey { 6 | static final Set _registry = {}; 7 | 8 | final Key parentKey; 9 | final String id; 10 | 11 | const AnchorKey._(this.parentKey, this.id) : super.constructor(); 12 | 13 | static AnchorKey? of(Key? parentKey, StyledElement? id) { 14 | final key = forId(parentKey, id?.elementId); 15 | if (key == null || _registry.contains(key)) { 16 | // Invalid id or already created a key with this id: silently ignore 17 | return null; 18 | } 19 | _registry.add(key); 20 | return key; 21 | } 22 | 23 | static AnchorKey? forId(Key? parentKey, String? id) { 24 | if (parentKey == null || id == null || id.isEmpty || id == "[[No ID]]") { 25 | return null; 26 | } 27 | 28 | return AnchorKey._(parentKey, id); 29 | } 30 | 31 | @override 32 | bool operator ==(Object other) => 33 | identical(this, other) || 34 | other is AnchorKey && 35 | runtimeType == other.runtimeType && 36 | parentKey == other.parentKey && 37 | id == other.id; 38 | 39 | @override 40 | int get hashCode => parentKey.hashCode ^ id.hashCode; 41 | 42 | @override 43 | String toString() { 44 | return 'AnchorKey{parentKey: $parentKey, id: #$id}'; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/widget/simple_html/src/interactable_element.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: constant_identifier_names 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:html/dom.dart' as dom; 5 | 6 | import '../style.dart'; 7 | import 'styled_element.dart'; 8 | 9 | /// An [InteractableElement] is a [StyledElement] that takes user gestures (e.g. tap). 10 | class InteractableElement extends StyledElement { 11 | String? href; 12 | 13 | InteractableElement({ 14 | required super.name, 15 | required super.children, 16 | required super.style, 17 | required this.href, 18 | required dom.Node node, 19 | required super.elementId, 20 | }) : super(node: node as dom.Element?); 21 | } 22 | 23 | /// A [Gesture] indicates the type of interaction by a user. 24 | enum Gesture { 25 | TAP, 26 | } 27 | 28 | StyledElement parseInteractableElement( 29 | dom.Element element, List children) { 30 | switch (element.localName) { 31 | case "a": 32 | if (element.attributes.containsKey('href')) { 33 | return InteractableElement( 34 | name: element.localName!, 35 | children: children, 36 | href: element.attributes['href'], 37 | style: Style( 38 | color: Colors.blue, 39 | textDecoration: TextDecoration.underline, 40 | ), 41 | node: element, 42 | elementId: element.id); 43 | } 44 | // When tag have no href, it must be non clickable and without decoration. 45 | return StyledElement( 46 | name: element.localName!, 47 | children: children, 48 | style: Style(), 49 | node: element, 50 | elementId: element.id, 51 | ); 52 | 53 | /// will never be called, just to suppress missing return warning 54 | default: 55 | return InteractableElement( 56 | name: element.localName!, 57 | children: children, 58 | node: element, 59 | href: '', 60 | style: Style(), 61 | elementId: "[[No ID]]"); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /lib/widget/simple_html/src/utils.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../style.dart'; 4 | 5 | Map namedColors = { 6 | "White": "#FFFFFF", 7 | "Silver": "#C0C0C0", 8 | "Gray": "#808080", 9 | "Black": "#000000", 10 | "Red": "#FF0000", 11 | "Maroon": "#800000", 12 | "Yellow": "#FFFF00", 13 | "Olive": "#808000", 14 | "Lime": "#00FF00", 15 | "Green": "#008000", 16 | "Aqua": "#00FFFF", 17 | "Teal": "#008080", 18 | "Blue": "#0000FF", 19 | "Navy": "#000080", 20 | "Fuchsia": "#FF00FF", 21 | "Purple": "#800080", 22 | }; 23 | 24 | class Context { 25 | T data; 26 | 27 | Context(this.data); 28 | } 29 | 30 | // This class is a workaround so that both an image 31 | // and a link can detect taps at the same time. 32 | class MultipleTapGestureDetector extends InheritedWidget { 33 | final void Function()? onTap; 34 | 35 | const MultipleTapGestureDetector({ 36 | super.key, 37 | required super.child, 38 | required this.onTap, 39 | }); 40 | 41 | static MultipleTapGestureDetector? of(BuildContext context) { 42 | return context 43 | .dependOnInheritedWidgetOfExactType(); 44 | } 45 | 46 | @override 47 | bool updateShouldNotify(MultipleTapGestureDetector oldWidget) => false; 48 | } 49 | 50 | class CustomBorderSide { 51 | CustomBorderSide({ 52 | this.color = const Color(0xFF000000), 53 | this.width = 1.0, 54 | this.style = BorderStyle.none, 55 | }) : assert(width >= 0.0); 56 | 57 | Color? color; 58 | double width; 59 | BorderStyle style; 60 | } 61 | 62 | extension TextTransformUtil on String? { 63 | String? transformed(TextTransform? transform) { 64 | if (this == null) return null; 65 | if (transform == TextTransform.uppercase) { 66 | return this!.toUpperCase(); 67 | } else if (transform == TextTransform.lowercase) { 68 | return this!.toLowerCase(); 69 | } else if (transform == TextTransform.capitalize) { 70 | final stringBuffer = StringBuffer(); 71 | 72 | var capitalizeNext = true; 73 | for (final letter in this!.toLowerCase().codeUnits) { 74 | // UTF-16: A-Z => 65-90, a-z => 97-122. 75 | if (capitalizeNext && letter >= 97 && letter <= 122) { 76 | stringBuffer.writeCharCode(letter - 32); 77 | capitalizeNext = false; 78 | } else { 79 | // UTF-16: 32 == space, 46 == period 80 | if (letter == 32 || letter == 46) capitalizeNext = true; 81 | stringBuffer.writeCharCode(letter); 82 | } 83 | } 84 | 85 | return stringBuffer.toString(); 86 | } else { 87 | return this; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /linux/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral 2 | -------------------------------------------------------------------------------- /linux/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This file controls Flutter-level build steps. It should not be edited. 2 | cmake_minimum_required(VERSION 3.10) 3 | 4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 5 | 6 | # Configuration provided via flutter tool. 7 | include(${EPHEMERAL_DIR}/generated_config.cmake) 8 | 9 | # TODO: Move the rest of this into files in ephemeral. See 10 | # https://github.com/flutter/flutter/issues/57146. 11 | 12 | # Serves the same purpose as list(TRANSFORM ... PREPEND ...), 13 | # which isn't available in 3.10. 14 | function(list_prepend LIST_NAME PREFIX) 15 | set(NEW_LIST "") 16 | foreach(element ${${LIST_NAME}}) 17 | list(APPEND NEW_LIST "${PREFIX}${element}") 18 | endforeach(element) 19 | set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) 20 | endfunction() 21 | 22 | # === Flutter Library === 23 | # System-level dependencies. 24 | find_package(PkgConfig REQUIRED) 25 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 26 | pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) 27 | pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) 28 | 29 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") 30 | 31 | # Published to parent scope for install step. 32 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 33 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 34 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 35 | set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) 36 | 37 | list(APPEND FLUTTER_LIBRARY_HEADERS 38 | "fl_basic_message_channel.h" 39 | "fl_binary_codec.h" 40 | "fl_binary_messenger.h" 41 | "fl_dart_project.h" 42 | "fl_engine.h" 43 | "fl_json_message_codec.h" 44 | "fl_json_method_codec.h" 45 | "fl_message_codec.h" 46 | "fl_method_call.h" 47 | "fl_method_channel.h" 48 | "fl_method_codec.h" 49 | "fl_method_response.h" 50 | "fl_plugin_registrar.h" 51 | "fl_plugin_registry.h" 52 | "fl_standard_message_codec.h" 53 | "fl_standard_method_codec.h" 54 | "fl_string_codec.h" 55 | "fl_value.h" 56 | "fl_view.h" 57 | "flutter_linux.h" 58 | ) 59 | list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") 60 | add_library(flutter INTERFACE) 61 | target_include_directories(flutter INTERFACE 62 | "${EPHEMERAL_DIR}" 63 | ) 64 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") 65 | target_link_libraries(flutter INTERFACE 66 | PkgConfig::GTK 67 | PkgConfig::GLIB 68 | PkgConfig::GIO 69 | ) 70 | add_dependencies(flutter flutter_assemble) 71 | 72 | # === Flutter tool backend === 73 | # _phony_ is a non-existent file to force this command to run every time, 74 | # since currently there's no way to get a full input/output list from the 75 | # flutter tool. 76 | add_custom_command( 77 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 78 | ${CMAKE_CURRENT_BINARY_DIR}/_phony_ 79 | COMMAND ${CMAKE_COMMAND} -E env 80 | ${FLUTTER_TOOL_ENVIRONMENT} 81 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" 82 | ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} 83 | VERBATIM 84 | ) 85 | add_custom_target(flutter_assemble DEPENDS 86 | "${FLUTTER_LIBRARY}" 87 | ${FLUTTER_LIBRARY_HEADERS} 88 | ) 89 | -------------------------------------------------------------------------------- /linux/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | void fl_register_plugins(FlPluginRegistry* registry) { 17 | g_autoptr(FlPluginRegistrar) bitsdojo_window_linux_registrar = 18 | fl_plugin_registry_get_registrar_for_plugin(registry, "BitsdojoWindowPlugin"); 19 | bitsdojo_window_plugin_register_with_registrar(bitsdojo_window_linux_registrar); 20 | g_autoptr(FlPluginRegistrar) desktop_webview_window_registrar = 21 | fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopWebviewWindowPlugin"); 22 | desktop_webview_window_plugin_register_with_registrar(desktop_webview_window_registrar); 23 | g_autoptr(FlPluginRegistrar) isar_flutter_libs_registrar = 24 | fl_plugin_registry_get_registrar_for_plugin(registry, "IsarFlutterLibsPlugin"); 25 | isar_flutter_libs_plugin_register_with_registrar(isar_flutter_libs_registrar); 26 | g_autoptr(FlPluginRegistrar) screen_retriever_registrar = 27 | fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin"); 28 | screen_retriever_plugin_register_with_registrar(screen_retriever_registrar); 29 | g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = 30 | fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); 31 | url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); 32 | g_autoptr(FlPluginRegistrar) window_manager_registrar = 33 | fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin"); 34 | window_manager_plugin_register_with_registrar(window_manager_registrar); 35 | } 36 | -------------------------------------------------------------------------------- /linux/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void fl_register_plugins(FlPluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /linux/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | bitsdojo_window_linux 7 | desktop_webview_window 8 | isar_flutter_libs 9 | screen_retriever 10 | url_launcher_linux 11 | window_manager 12 | ) 13 | 14 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 15 | ) 16 | 17 | set(PLUGIN_BUNDLED_LIBRARIES) 18 | 19 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 20 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) 21 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 22 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 23 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 24 | endforeach(plugin) 25 | 26 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 27 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) 28 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 29 | endforeach(ffi_plugin) 30 | -------------------------------------------------------------------------------- /linux/main.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | int main(int argc, char** argv) { 4 | g_autoptr(MyApplication) app = my_application_new(); 5 | return g_application_run(G_APPLICATION(app), argc, argv); 6 | } 7 | -------------------------------------------------------------------------------- /linux/my_application.h: -------------------------------------------------------------------------------- 1 | #ifndef FLUTTER_MY_APPLICATION_H_ 2 | #define FLUTTER_MY_APPLICATION_H_ 3 | 4 | #include 5 | 6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, 7 | GtkApplication) 8 | 9 | /** 10 | * my_application_new: 11 | * 12 | * Creates a new Flutter-based application. 13 | * 14 | * Returns: a new #MyApplication. 15 | */ 16 | MyApplication* my_application_new(); 17 | 18 | #endif // FLUTTER_MY_APPLICATION_H_ 19 | -------------------------------------------------------------------------------- /macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/dgph 7 | **/xcuserdata/ 8 | -------------------------------------------------------------------------------- /macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | import bitsdojo_window_macos 9 | import desktop_webview_window 10 | import isar_flutter_libs 11 | import package_info_plus 12 | import path_provider_foundation 13 | import protocol_handler_macos 14 | import screen_retriever 15 | import share_plus 16 | import sqflite 17 | import url_launcher_macos 18 | import video_player_avfoundation 19 | import wakelock_plus 20 | import window_manager 21 | 22 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 23 | BitsdojoWindowPlugin.register(with: registry.registrar(forPlugin: "BitsdojoWindowPlugin")) 24 | DesktopWebviewWindowPlugin.register(with: registry.registrar(forPlugin: "DesktopWebviewWindowPlugin")) 25 | IsarFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "IsarFlutterLibsPlugin")) 26 | FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) 27 | PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) 28 | ProtocolHandlerMacosPlugin.register(with: registry.registrar(forPlugin: "ProtocolHandlerMacosPlugin")) 29 | ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin")) 30 | SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) 31 | SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) 32 | UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) 33 | FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin")) 34 | WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin")) 35 | WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin")) 36 | } 37 | -------------------------------------------------------------------------------- /macos/Podfile: -------------------------------------------------------------------------------- 1 | platform :osx, '10.14' 2 | 3 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 4 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 5 | 6 | project 'Runner', { 7 | 'Debug' => :debug, 8 | 'Profile' => :release, 9 | 'Release' => :release, 10 | } 11 | 12 | def flutter_root 13 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) 14 | unless File.exist?(generated_xcode_build_settings_path) 15 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" 16 | end 17 | 18 | File.foreach(generated_xcode_build_settings_path) do |line| 19 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 20 | return matches[1].strip if matches 21 | end 22 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" 23 | end 24 | 25 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 26 | 27 | flutter_macos_podfile_setup 28 | 29 | target 'Runner' do 30 | use_frameworks! 31 | use_modular_headers! 32 | 33 | flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) 34 | end 35 | 36 | post_install do |installer| 37 | installer.pods_project.targets.each do |target| 38 | flutter_additional_macos_build_settings(target) 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 64 | 65 | 71 | 73 | 79 | 80 | 81 | 82 | 84 | 85 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @NSApplicationMain 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "author": "icons_launcher", 4 | "version": 1 5 | }, 6 | "images": [ 7 | { 8 | "size": "16x16", 9 | "idiom": "mac", 10 | "filename": "app_icon_16.png", 11 | "scale": "1x" 12 | }, 13 | { 14 | "size": "16x16", 15 | "idiom": "mac", 16 | "filename": "app_icon_32.png", 17 | "scale": "2x" 18 | }, 19 | { 20 | "size": "32x32", 21 | "idiom": "mac", 22 | "filename": "app_icon_32.png", 23 | "scale": "1x" 24 | }, 25 | { 26 | "size": "32x32", 27 | "idiom": "mac", 28 | "filename": "app_icon_64.png", 29 | "scale": "2x" 30 | }, 31 | { 32 | "size": "128x128", 33 | "idiom": "mac", 34 | "filename": "app_icon_128.png", 35 | "scale": "1x" 36 | }, 37 | { 38 | "size": "128x128", 39 | "idiom": "mac", 40 | "filename": "app_icon_256.png", 41 | "scale": "2x" 42 | }, 43 | { 44 | "size": "256x256", 45 | "idiom": "mac", 46 | "filename": "app_icon_256.png", 47 | "scale": "1x" 48 | }, 49 | { 50 | "size": "256x256", 51 | "idiom": "mac", 52 | "filename": "app_icon_512.png", 53 | "scale": "2x" 54 | }, 55 | { 56 | "size": "512x512", 57 | "idiom": "mac", 58 | "filename": "app_icon_512.png", 59 | "scale": "1x" 60 | }, 61 | { 62 | "size": "512x512", 63 | "idiom": "mac", 64 | "filename": "app_icon_1024.png", 65 | "scale": "2x" 66 | } 67 | ] 68 | } -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = yoyo 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = io.github.d1y.movie.movie 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2022 d1y 15 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | com.apple.security.network.client 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | CFBundleURLTypes 30 | 31 | 32 | CFBundleTypeRole 33 | Editor 34 | CFBundleURLName 35 | 36 | CFBundleURLSchemes 37 | 38 | yoyo 39 | 40 | 41 | 42 | NSPrincipalClass 43 | NSApplication 44 | FLTEnableImpeller 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | import bitsdojo_window_macos 4 | 5 | class MainFlutterWindow: BitsdojoWindow { 6 | 7 | override func bitsdojo_window_configure() -> UInt { 8 | return BDW_CUSTOM_FRAME 9 | } 10 | 11 | override func awakeFromNib() { 12 | let flutterViewController = FlutterViewController.init() 13 | let windowFrame = self.frame 14 | self.contentViewController = flutterViewController 15 | self.setFrame(windowFrame, display: true) 16 | 17 | RegisterGeneratedPlugins(registry: flutterViewController) 18 | 19 | super.awakeFromNib() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.network.client 8 | 9 | com.apple.security.network.server 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /macos/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /packages/command_palette/.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 | # Android related 34 | **/android/**/gradle-wrapper.jar 35 | **/android/.gradle 36 | **/android/captures/ 37 | **/android/gradlew 38 | **/android/gradlew.bat 39 | **/android/local.properties 40 | **/android/**/GeneratedPluginRegistrant.java 41 | 42 | # iOS/XCode related 43 | **/ios/**/*.mode1v3 44 | **/ios/**/*.mode2v3 45 | **/ios/**/*.moved-aside 46 | **/ios/**/*.pbxuser 47 | **/ios/**/*.perspectivev3 48 | **/ios/**/*sync/ 49 | **/ios/**/.sconsign.dblite 50 | **/ios/**/.tags* 51 | **/ios/**/.vagrant/ 52 | **/ios/**/DerivedData/ 53 | **/ios/**/Icon? 54 | **/ios/**/Pods/ 55 | **/ios/**/.symlinks/ 56 | **/ios/**/profile 57 | **/ios/**/xcuserdata 58 | **/ios/.generated/ 59 | **/ios/Flutter/App.framework 60 | **/ios/Flutter/Flutter.framework 61 | **/ios/Flutter/Flutter.podspec 62 | **/ios/Flutter/Generated.xcconfig 63 | **/ios/Flutter/ephemeral 64 | **/ios/Flutter/app.flx 65 | **/ios/Flutter/app.zip 66 | **/ios/Flutter/flutter_assets/ 67 | **/ios/Flutter/flutter_export_environment.sh 68 | **/ios/ServiceDefinitions.json 69 | **/ios/Runner/GeneratedPluginRegistrant.* 70 | 71 | # Exceptions to above rules. 72 | !**/ios/**/default.mode1v3 73 | !**/ios/**/default.mode2v3 74 | !**/ios/**/default.pbxuser 75 | !**/ios/**/default.perspectivev3 76 | 77 | # ignore coverage file 78 | coverage 79 | .fvm/flutter_sdk 80 | -------------------------------------------------------------------------------- /packages/command_palette/.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: ffb2ecea5223acdd139a5039be2f9c796962833d 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /packages/command_palette/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Tyler Norbury 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/command_palette/lib/command_palette.dart: -------------------------------------------------------------------------------- 1 | library command_palette; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import 'src/models/command_palette_action.dart'; 6 | import 'src/models/command_palette_style.dart'; 7 | 8 | export 'src/command_palette.dart'; 9 | export 'src/models/command_palette_action.dart'; 10 | export 'src/models/matched_command_palette_action.dart'; 11 | export 'src/models/command_palette_style.dart'; 12 | export 'src/models/command_palette_config.dart'; 13 | export 'src/utils/filter.dart'; 14 | export 'src/widgets/keyboard_key_icon.dart'; 15 | 16 | /// Defines the type of function to be used for filtering command palette 17 | /// actions. 18 | /// Given [query] and [allActions], the function should determine the subset of 19 | /// actions to return based on the function 20 | typedef ActionFilter = List Function( 21 | String query, List allActions); 22 | 23 | /// Builder used for the action options. 24 | /// Provides the following arguments: 25 | /// * [style]: The style provided to the command palette 26 | /// * [action]: The action we're building a widget for 27 | /// * [isHighlighted]: Whether or not the action is the currently highlighted 28 | /// one (selected by the cursor) 29 | /// * [onSelected]: Callback that's to be called when the action is clicked on 30 | /// * [searchTerms]: Terms used to search. Taken from the text entered into the 31 | /// text field, splitting on space. 32 | typedef ActionBuilder = Widget Function( 33 | BuildContext context, 34 | CommandPaletteStyle style, 35 | CommandPaletteAction action, 36 | bool isHighlighted, 37 | VoidCallback onSelected, 38 | List searchTerms, 39 | ); 40 | -------------------------------------------------------------------------------- /packages/command_palette/lib/src/models/matched_command_palette_action.dart: -------------------------------------------------------------------------------- 1 | import 'package:command_palette/command_palette.dart'; 2 | 3 | /// An action that was matched to the entered query. Contains both the action 4 | /// itself and a list of the matches contained within 5 | class MatchedCommandPaletteAction extends CommandPaletteAction { 6 | final List? matches; 7 | 8 | MatchedCommandPaletteAction(CommandPaletteAction action, this.matches) 9 | // ignore: deprecated_member_use_from_same_package 10 | : super( 11 | label: action.label, 12 | actionType: action.actionType, 13 | childrenActions: action.childrenActions, 14 | description: action.description, 15 | onSelect: action.onSelect, 16 | shortcut: action.shortcut, 17 | id: action.id, 18 | leading: action.leading, 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /packages/command_palette/lib/src/widgets/keyboard_key_icon.dart: -------------------------------------------------------------------------------- 1 | import 'package:command_palette/src/controller/command_palette_controller.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | /// Creates an icon which represents a keyboard key. 5 | /// This is done either with existing [IconData] which represents the key, or 6 | /// with a [String] 7 | class KeyboardKeyIcon extends StatelessWidget { 8 | final IconData? icon; 9 | final String? iconString; 10 | final Color? color; 11 | const KeyboardKeyIcon({ 12 | Key? key, 13 | this.icon, 14 | this.iconString, 15 | this.color, 16 | }) : assert((icon != null && iconString == null) || 17 | (icon == null && iconString != null)), 18 | super(key: key); 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | CommandPaletteController controller = 23 | CommandPaletteControllerProvider.of(context); 24 | final outline = Theme.of(context).dividerColor; 25 | 26 | TextStyle? style = controller.style.actionDescriptionTextStyle; 27 | if (color != null) { 28 | style = style?.merge(TextStyle(color: color)); 29 | } 30 | 31 | return Container( 32 | padding: const EdgeInsets.symmetric( 33 | horizontal: 4, 34 | vertical: 2, 35 | ), 36 | margin: const EdgeInsets.only(right: 4), 37 | decoration: BoxDecoration( 38 | border: Border.all(color: outline), 39 | borderRadius: BorderRadius.circular(5), 40 | ), 41 | child: icon != null 42 | ? Icon( 43 | icon, 44 | size: controller.style.actionLabelTextStyle?.fontSize, 45 | color: color, 46 | ) 47 | : Text( 48 | iconString!.toUpperCase(), 49 | style: style, 50 | ), 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/command_palette/lib/src/widgets/options/option_highlighter.dart: -------------------------------------------------------------------------------- 1 | import 'package:command_palette/src/models/matched_command_palette_action.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | /// Highlights the label of a command option 5 | class OptionHighlighter extends StatelessWidget { 6 | final MatchedCommandPaletteAction action; 7 | final TextStyle textStyle; 8 | final TextStyle textStyleHighlight; 9 | final TextAlign textAlign; 10 | 11 | OptionHighlighter({ 12 | Key? key, 13 | required this.action, 14 | required this.textAlign, 15 | required this.textStyle, 16 | required this.textStyleHighlight, 17 | }) : assert(action.matches != null), 18 | super(key: key); 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | List formattedText = []; 23 | 24 | int endOfLastSubString = 0; 25 | 26 | for (final match in action.matches!) { 27 | // print out all the non-highlighted text up to this point 28 | formattedText.add( 29 | TextSpan( 30 | text: action.label.substring(endOfLastSubString, match.start), 31 | style: textStyle, 32 | ), 33 | ); 34 | 35 | // now print the highlighted text 36 | formattedText.add( 37 | TextSpan( 38 | text: action.label.substring(match.start, match.end), 39 | style: textStyleHighlight, 40 | ), 41 | ); 42 | 43 | endOfLastSubString = match.end; 44 | } 45 | 46 | // if there is still some text at the very end, we'll print that out too. 47 | if (endOfLastSubString != action.label.length) { 48 | formattedText.add( 49 | TextSpan( 50 | text: action.label.substring(endOfLastSubString, action.label.length), 51 | style: textStyle, 52 | ), 53 | ); 54 | } 55 | 56 | return RichText( 57 | text: TextSpan(children: formattedText), 58 | textAlign: textAlign, 59 | ); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /packages/command_palette/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: command_palette 2 | description: Flutter implementation of a Command Palette. Can be brought up via a keyboard shortcut. 3 | version: 0.7.3 4 | homepage: https://github.com/TNorbury/command_palette 5 | issue_tracker: https://github.com/TNorbury/command_palette/issues 6 | repository: https://github.com/TNorbury/command_palette 7 | platforms: 8 | android: 9 | ios: 10 | linux: 11 | macos: 12 | web: 13 | windows: 14 | 15 | 16 | environment: 17 | sdk: ">=2.12.0 <3.0.0" 18 | flutter: ">=1.17.0" 19 | 20 | dependencies: 21 | flutter: 22 | sdk: flutter 23 | substring_highlight: ^1.0.33 24 | woozy_search: ^2.0.3 25 | 26 | dev_dependencies: 27 | flutter_test: 28 | sdk: flutter 29 | flutter_lints: ^2.0.1 30 | 31 | flutter: 32 | 33 | -------------------------------------------------------------------------------- /packages/flappy_search_bar_ns/.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 | .packages 28 | .pub-cache/ 29 | .pub/ 30 | build/ 31 | 32 | # Android related 33 | **/android/**/gradle-wrapper.jar 34 | **/android/.gradle 35 | **/android/captures/ 36 | **/android/gradlew 37 | **/android/gradlew.bat 38 | **/android/local.properties 39 | **/android/**/GeneratedPluginRegistrant.java 40 | 41 | # iOS/XCode related 42 | **/ios/**/*.mode1v3 43 | **/ios/**/*.mode2v3 44 | **/ios/**/*.moved-aside 45 | **/ios/**/*.pbxuser 46 | **/ios/**/*.perspectivev3 47 | **/ios/**/*sync/ 48 | **/ios/**/.sconsign.dblite 49 | **/ios/**/.tags* 50 | **/ios/**/.vagrant/ 51 | **/ios/**/DerivedData/ 52 | **/ios/**/Icon? 53 | **/ios/**/Pods/ 54 | **/ios/**/.symlinks/ 55 | **/ios/**/profile 56 | **/ios/**/xcuserdata 57 | **/ios/.generated/ 58 | **/ios/Flutter/App.framework 59 | **/ios/Flutter/Flutter.framework 60 | **/ios/Flutter/Generated.xcconfig 61 | **/ios/Flutter/app.flx 62 | **/ios/Flutter/app.zip 63 | **/ios/Flutter/flutter_assets/ 64 | **/ios/ServiceDefinitions.json 65 | **/ios/Runner/GeneratedPluginRegistrant.* 66 | 67 | # Exceptions to above rules. 68 | !**/ios/**/default.mode1v3 69 | !**/ios/**/default.mode2v3 70 | !**/ios/**/default.pbxuser 71 | !**/ios/**/default.perspectivev3 72 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 73 | 74 | example/ios/Flutter/flutter_export_environment.sh 75 | 76 | example/ios/Flutter/Flutter.podspec 77 | -------------------------------------------------------------------------------- /packages/flappy_search_bar_ns/.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: b712a172f9694745f50505c93340883493b505e5 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /packages/flappy_search_bar_ns/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 Cyllene https://www.groupe-cyllene.com/ 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /packages/flappy_search_bar_ns/lib/scaled_tile.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; 2 | 3 | /// Class only use in order to give access to StaggeredTile to users 4 | class ScaledTile extends StaggeredTile { 5 | /// Creates a [ScaledTile] with the given [crossAxisCellCount] that 6 | /// fit its main axis extent to its content. 7 | /// 8 | /// This tile will have a fixed main axis extent. 9 | ScaledTile.fit( 10 | int crossAxisCellCount, 11 | ) : super.fit(crossAxisCellCount); 12 | 13 | /// Creates a [ScaledTile] with the given [crossAxisCellCount] and 14 | /// [mainAxisExtent]. 15 | /// 16 | /// This tile will have a fixed main axis extent. 17 | ScaledTile.extent( 18 | int crossAxisCellCount, 19 | double mainAxisExtent, 20 | ) : super.extent(crossAxisCellCount, mainAxisExtent); 21 | 22 | /// Creates a [ScaledTile] with the given [crossAxisCellCount] and 23 | /// [mainAxisCellCount]. 24 | /// 25 | /// The main axis extent of this tile will be the length of 26 | /// [mainAxisCellCount] cells (inner spacings included). 27 | ScaledTile.count( 28 | int crossAxisCellCount, 29 | num mainAxisCellCount, 30 | ) : super.count(crossAxisCellCount, mainAxisCellCount as double?); 31 | } 32 | -------------------------------------------------------------------------------- /packages/flappy_search_bar_ns/lib/search_bar_style.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class SearchBarStyle { 4 | final Color backgroundColor; 5 | final EdgeInsetsGeometry padding; 6 | final BorderRadius borderRadius; 7 | 8 | const SearchBarStyle( 9 | {this.backgroundColor = const Color.fromRGBO(142, 142, 147, .15), 10 | this.padding = const EdgeInsets.all(5.0), 11 | this.borderRadius = const BorderRadius.all(Radius.circular(5.0))}); 12 | } 13 | -------------------------------------------------------------------------------- /packages/flappy_search_bar_ns/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flappy_search_bar 2 | description: A SearchBar widget automatizing most of your asynchronous searchs cases. 3 | version: 1.7.2 4 | homepage: https://github.com/smartnsoft/flappy_search_bar 5 | 6 | environment: 7 | sdk: '>=2.12.0 <3.0.0' 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | async: ^2.6.1 13 | flutter_staggered_grid_view: ^0.4.0 14 | 15 | dev_dependencies: 16 | flutter_test: 17 | sdk: flutter 18 | 19 | # For information on the generic Dart part of this file, see the 20 | # following page: https://dart.dev/tools/pub/pubspec 21 | 22 | # The following section is specific to Flutter. 23 | flutter: 24 | 25 | # To add assets to your package, add an assets section, like this: 26 | # assets: 27 | # - images/a_dot_burr.jpeg 28 | # - images/a_dot_ham.jpeg 29 | # 30 | # For details regarding assets in packages, see 31 | # https://flutter.dev/assets-and-images/#from-packages 32 | # 33 | # An image asset can refer to one or more resolution-specific "variants", see 34 | # https://flutter.dev/assets-and-images/#resolution-aware. 35 | 36 | # To add custom fonts to your package, add a fonts section here, 37 | # in this "flutter" section. Each entry in this list should have a 38 | # "family" key with the font family name, and a "fonts" key with a 39 | # list giving the asset and other descriptors for the font. For 40 | # example: 41 | # fonts: 42 | # - family: Schyler 43 | # fonts: 44 | # - asset: fonts/Schyler-Regular.ttf 45 | # - asset: fonts/Schyler-Italic.ttf 46 | # style: italic 47 | # - family: Trajan Pro 48 | # fonts: 49 | # - asset: fonts/TrajanPro.ttf 50 | # - asset: fonts/TrajanPro_Bold.ttf 51 | # weight: 700 52 | # 53 | # For details regarding fonts in packages, see 54 | # https://flutter.dev/custom-fonts/#from-packages 55 | -------------------------------------------------------------------------------- /packages/flutter_cupertino_settings/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .atom/ 3 | .idea 4 | .packages 5 | .pub/ 6 | .dart_tool 7 | .vscode 8 | packages 9 | ios/ 10 | pubspec.lock -------------------------------------------------------------------------------- /packages/flutter_cupertino_settings/lib/flutter_cupertino_settings.dart: -------------------------------------------------------------------------------- 1 | library flutter_cupertino_settings; 2 | 3 | import 'dart:io'; 4 | 5 | import 'package:flutter/foundation.dart'; 6 | import 'package:flutter/material.dart' show Theme; 7 | import 'package:flutter/cupertino.dart'; 8 | import 'package:flutter/services.dart'; 9 | 10 | part 'widgets/button.dart'; 11 | part 'widgets/control.dart'; 12 | part 'widgets/description.dart'; 13 | part 'widgets/header.dart'; 14 | part 'widgets/link.dart'; 15 | part 'widgets/secret.dart'; 16 | part 'widgets/selection.dart'; 17 | part 'widgets/spacer.dart'; 18 | part 'widgets/widget.dart'; 19 | 20 | const double CS_ITEM_HEIGHT = 50.0; 21 | const EdgeInsets CS_ITEM_PADDING = 22 | EdgeInsets.symmetric(horizontal: 10, vertical: 1); 23 | const double CS_TITLE_FONT_SIZE = 16.0; 24 | const double CS_SUBTITLE_FONT_SIZE = 11.0; 25 | const double CS_HEADER_FONT_SIZE = 14.0; 26 | const double CS_DESCRIPTION_FONT_SIZE = 13.0; 27 | const double CS_ITEM_NAME_SIZE = 15.0; 28 | const EdgeInsets CS_ICON_PADDING = EdgeInsets.only( 29 | right: 10.0, 30 | left: 4.0, 31 | ); 32 | const CSWidgetStyle CS_DEFAULT_STYLE = CSWidgetStyle(); 33 | const double CS_CHECK_SIZE = 20.0; 34 | const double CS_CHEVRON_SIZE = 17.0; 35 | 36 | /// Event for [CSSelection] 37 | typedef void SelectionCallback(int selected); 38 | 39 | TextStyle basicTextStyle(BuildContext context) => 40 | (kIsWeb 41 | ? Theme.of(context).textTheme.titleSmall 42 | : Platform.isIOS 43 | ? CupertinoTheme.of(context).textTheme.textStyle 44 | : Theme.of(context).textTheme.titleSmall) ?? 45 | TextStyle(); 46 | 47 | class CupertinoSettings extends StatelessWidget { 48 | final List items; 49 | final bool shrinkWrap; 50 | final ScrollController? scrollController; 51 | 52 | const CupertinoSettings({ 53 | required this.items, 54 | this.scrollController, 55 | this.shrinkWrap = false, 56 | }); 57 | 58 | @override 59 | Widget build(BuildContext context) { 60 | return Container( 61 | color: CupertinoColors.systemGroupedBackground.resolveFrom(context), 62 | child: SafeArea( 63 | bottom: false, 64 | child: shrinkWrap 65 | ? ListView.builder( 66 | shrinkWrap: shrinkWrap, 67 | itemCount: items.length, 68 | controller: scrollController, 69 | itemBuilder: (BuildContext context, int index) => items[index], 70 | ) 71 | : Column( 72 | children: [ 73 | Expanded( 74 | child: ListView.builder( 75 | shrinkWrap: shrinkWrap, 76 | itemCount: items.length, 77 | controller: scrollController, 78 | itemBuilder: (BuildContext context, int index) => 79 | items[index], 80 | ), 81 | ), 82 | ], 83 | ), 84 | ), 85 | ); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /packages/flutter_cupertino_settings/lib/widgets/button.dart: -------------------------------------------------------------------------------- 1 | part of flutter_cupertino_settings; 2 | 3 | /// A button-cell inside [CupertinoSettings] 4 | /// 3 different types are available (they only affect the design): 5 | /// [CSButtonType.DESTRUCTIVE] Red and centered 6 | /// [CSButtonType.DEFAULT] Blue and left aligned 7 | /// [CSButtonType.DEFAULT_CENTER] Blue and centered 8 | /// Provides the correct paddings and text properties 9 | /// 10 | /// It is quite complex: 11 | /// 12 | /// -- Widget 13 | /// |- Flex 14 | /// |- Expand 15 | /// |- CupertinoButton 16 | /// |- Container (<--- For text-alignment) 17 | /// |- Text 18 | /// 19 | /// This "hack" is mandatory to archive that... 20 | /// 1) The button can be aligned 21 | /// 2) The entire row is touch-sensitive 22 | class CSButton extends CSWidget { 23 | final CSButtonType buttonType; 24 | final String text; 25 | final VoidCallback pressed; 26 | final double fontSize; 27 | 28 | CSButton( 29 | this.buttonType, 30 | this.text, 31 | this.pressed, { 32 | CSWidgetStyle style = CS_DEFAULT_STYLE, 33 | this.fontSize = CS_TITLE_FONT_SIZE, 34 | }) : super( 35 | Flex( 36 | direction: Axis.horizontal, 37 | children: [ 38 | Expanded( 39 | child: CupertinoButton( 40 | padding: EdgeInsets.zero, 41 | onPressed: pressed, 42 | child: Container( 43 | alignment: buttonType.alignment, 44 | child: Text( 45 | text, 46 | style: TextStyle( 47 | color: buttonType.color, 48 | fontSize: fontSize, 49 | ), 50 | ), 51 | ), 52 | ), 53 | ), 54 | ], 55 | ), 56 | style: style, 57 | ); 58 | } 59 | 60 | /// Defines different types for [CSButton] 61 | /// Specifies color and alignment 62 | class CSButtonType { 63 | static const CSButtonType DESTRUCTIVE = CSButtonType( 64 | CupertinoColors.destructiveRed, 65 | AlignmentDirectional.center, 66 | ); 67 | static const CSButtonType DEFAULT = CSButtonType( 68 | CupertinoColors.systemBlue, 69 | AlignmentDirectional.centerStart, 70 | ); 71 | static const CSButtonType DEFAULT_CENTER = CSButtonType( 72 | CupertinoColors.systemBlue, 73 | AlignmentDirectional.center, 74 | ); 75 | 76 | final Color color; 77 | final AlignmentGeometry alignment; 78 | 79 | const CSButtonType(this.color, this.alignment); 80 | } 81 | -------------------------------------------------------------------------------- /packages/flutter_cupertino_settings/lib/widgets/control.dart: -------------------------------------------------------------------------------- 1 | part of flutter_cupertino_settings; 2 | 3 | /// A title [name] in combination with any widget [contentWidget] 4 | /// extends [CSWidget] 5 | /// Provides the correct paddings and text properties 6 | class CSControl extends CSWidget { 7 | final Widget? nameWidget; 8 | final Widget? contentWidget; 9 | final double fontSize; 10 | 11 | CSControl({ 12 | this.nameWidget, 13 | this.contentWidget, 14 | CSWidgetStyle style = CS_DEFAULT_STYLE, 15 | this.fontSize = CS_TITLE_FONT_SIZE, 16 | bool addPaddingToBorder = true, 17 | }) : super( 18 | _ControlWidget( 19 | fontSize: fontSize, 20 | contentWidget: contentWidget, 21 | nameWidget: nameWidget, 22 | ), 23 | style: style, 24 | addPaddingToBorder: addPaddingToBorder, 25 | ); 26 | } 27 | 28 | class _ControlWidget extends StatelessWidget { 29 | final Widget? nameWidget; 30 | final Widget? contentWidget; 31 | final double? fontSize; 32 | 33 | const _ControlWidget({ 34 | Key? key, 35 | this.fontSize, 36 | this.contentWidget, 37 | this.nameWidget, 38 | }) : super(key: key); 39 | 40 | @override 41 | Widget build(BuildContext context) { 42 | return DefaultTextStyle( 43 | style: basicTextStyle(context).copyWith( 44 | color: CupertinoColors.label.resolveFrom(context), 45 | fontSize: fontSize, 46 | ), 47 | child: Row( 48 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 49 | children: [ 50 | if (nameWidget != null) nameWidget!, 51 | if (contentWidget != null) contentWidget!, 52 | ], 53 | ), 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/flutter_cupertino_settings/lib/widgets/description.dart: -------------------------------------------------------------------------------- 1 | part of flutter_cupertino_settings; 2 | 3 | class CSDescription extends StatelessWidget { 4 | final String description; 5 | 6 | const CSDescription(this.description); 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return Container( 11 | padding: const EdgeInsets.fromLTRB(10, 7.5, 5, 5), 12 | color: CupertinoColors.systemGroupedBackground.resolveFrom(context), 13 | child: Text( 14 | description, 15 | style: basicTextStyle(context).copyWith( 16 | color: CupertinoColors.secondaryLabel.resolveFrom(context), 17 | fontSize: CS_DESCRIPTION_FONT_SIZE, 18 | height: 1.1, 19 | ), 20 | ), 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/flutter_cupertino_settings/lib/widgets/header.dart: -------------------------------------------------------------------------------- 1 | part of flutter_cupertino_settings; 2 | 3 | /// This widgets is used as a grouping separator. 4 | /// The [title] attribute is optional. 5 | class CSHeader extends StatelessWidget { 6 | final String title; 7 | 8 | const CSHeader(this.title); 9 | 10 | @override 11 | Widget build(BuildContext context) { 12 | return Container( 13 | padding: const EdgeInsets.only(left: 10.0, top: 30.0, bottom: 5.0), 14 | decoration: BoxDecoration( 15 | color: CupertinoColors.systemGroupedBackground.resolveFrom(context), 16 | border: Border( 17 | bottom: BorderSide( 18 | color: CupertinoColors.opaqueSeparator.resolveFrom(context), 19 | ), 20 | ), 21 | ), 22 | child: Text( 23 | title.toUpperCase(), 24 | style: basicTextStyle(context).copyWith( 25 | color: CupertinoColors.secondaryLabel.resolveFrom(context), 26 | fontSize: CS_HEADER_FONT_SIZE, 27 | ), 28 | ), 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/flutter_cupertino_settings/lib/widgets/secret.dart: -------------------------------------------------------------------------------- 1 | part of flutter_cupertino_settings; 2 | 3 | /// Provides a button for navigation 4 | class CSSecret extends StatefulWidget { 5 | final String text; 6 | final String secret; 7 | final double fontSize; 8 | final CSWidgetStyle style; 9 | final bool addPaddingToBorder; 10 | final String obscuringCharacter; 11 | 12 | CSSecret( 13 | this.text, 14 | this.secret, { 15 | this.style = CS_DEFAULT_STYLE, 16 | this.fontSize = CS_TITLE_FONT_SIZE, 17 | this.addPaddingToBorder = true, 18 | this.obscuringCharacter = '•', 19 | }); 20 | 21 | @override 22 | _CSSecretState createState() => _CSSecretState(); 23 | } 24 | 25 | class _CSSecretState extends State { 26 | bool _show = false; 27 | 28 | @override 29 | Widget build(BuildContext context) { 30 | return CSWidget( 31 | DefaultTextStyle( 32 | style: basicTextStyle(context).copyWith( 33 | color: CupertinoColors.label.resolveFrom(context), 34 | fontSize: widget.fontSize, 35 | ), 36 | child: Row( 37 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 38 | children: [ 39 | Text(widget.text), 40 | Row( 41 | children: [ 42 | Text( 43 | _show 44 | ? widget.secret 45 | : widget.obscuringCharacter * widget.secret.length, 46 | ), 47 | CupertinoButton( 48 | child: Icon( 49 | CupertinoIcons.eye_solid, 50 | size: CS_CHECK_SIZE, 51 | ), 52 | onPressed: () => setState(() => _show = !_show), 53 | ), 54 | ], 55 | ), 56 | ], 57 | ), 58 | ), 59 | style: widget.style, 60 | addPaddingToBorder: widget.addPaddingToBorder, 61 | ); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /packages/flutter_cupertino_settings/lib/widgets/selection.dart: -------------------------------------------------------------------------------- 1 | part of flutter_cupertino_settings; 2 | 3 | /// A selection view 4 | /// Allows to select between multiple items 5 | /// Every item is represented by a String 6 | /// 7 | /// If an item is selected, onSelected is called with its index 8 | /// 9 | /// eg: 10 | /// items = ["hello","world","flutter"] 11 | /// select "world" 12 | /// 13 | /// onSelected(1) 14 | 15 | class CSSelection extends StatelessWidget { 16 | final List> items; 17 | final void Function(T selected) onSelected; 18 | final T? currentSelection; 19 | final double fontSize; 20 | 21 | const CSSelection({ 22 | required this.items, 23 | required this.onSelected, 24 | this.currentSelection, 25 | this.fontSize = CS_TITLE_FONT_SIZE, 26 | }); 27 | 28 | @override 29 | Widget build(BuildContext context) { 30 | return Column( 31 | children: items.map((item) => createItem(context, item)).toList(), 32 | ); 33 | } 34 | 35 | Widget createItem(BuildContext context, CSSelectionItem item) { 36 | final text = Text(item.text, 37 | style: TextStyle( 38 | color: CupertinoColors.label.resolveFrom(context), 39 | fontSize: fontSize, 40 | )); 41 | final textWidget = item.subtitle == null 42 | ? text 43 | : Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ 44 | text, 45 | SizedBox(height: 2), 46 | Text(item.subtitle!, 47 | style: basicTextStyle(context).copyWith( 48 | color: CupertinoColors.secondaryLabel.resolveFrom(context), 49 | fontSize: CS_HEADER_FONT_SIZE)) 50 | ]); 51 | return CSWidget( 52 | CupertinoButton( 53 | onPressed: () { 54 | HapticFeedback.selectionClick(); 55 | onSelected(item.value); 56 | }, 57 | pressedOpacity: 1.0, 58 | padding: const EdgeInsets.fromLTRB(4, 8, 2, 8), 59 | child: Row( 60 | crossAxisAlignment: CrossAxisAlignment.center, 61 | children: [ 62 | Expanded(child: textWidget), 63 | Padding( 64 | padding: const EdgeInsets.only(right: 5.0), 65 | child: Icon( 66 | CupertinoIcons.check_mark, 67 | color: item.value == currentSelection 68 | ? CupertinoColors.activeBlue 69 | : const Color(0x00000000), 70 | size: CS_CHECK_SIZE, 71 | ), 72 | ), 73 | ], 74 | ), 75 | ), 76 | addPaddingToBorder: items.last != item, 77 | showTopBorder: item.showTopBorder, 78 | ); 79 | } 80 | } 81 | 82 | class CSSelectionItem { 83 | final T value; 84 | final String text; 85 | final String? subtitle; 86 | final bool showTopBorder; 87 | 88 | const CSSelectionItem({ 89 | required this.value, 90 | required this.text, 91 | this.subtitle, 92 | this.showTopBorder = false, 93 | }); 94 | } 95 | -------------------------------------------------------------------------------- /packages/flutter_cupertino_settings/lib/widgets/spacer.dart: -------------------------------------------------------------------------------- 1 | part of flutter_cupertino_settings; 2 | 3 | class CSSpacer extends StatelessWidget { 4 | final bool showBorder; 5 | 6 | const CSSpacer({ 7 | Key? key, 8 | this.showBorder = true, 9 | }) : super(key: key); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return Container( 14 | padding: const EdgeInsets.only(left: 10.0, top: 20.0, bottom: 5.0), 15 | decoration: BoxDecoration( 16 | color: CupertinoColors.systemGroupedBackground.resolveFrom(context), 17 | border: Border( 18 | bottom: showBorder 19 | ? BorderSide( 20 | color: CupertinoColors.opaqueSeparator.resolveFrom(context), 21 | ) 22 | : BorderSide.none, 23 | ), 24 | ), 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/flutter_cupertino_settings/lib/widgets/widget.dart: -------------------------------------------------------------------------------- 1 | part of flutter_cupertino_settings; 2 | 3 | /// Used to display a widget of any kind in [CupertinoSettings] 4 | /// It provices the correct height, color and border to create the intended look 5 | /// The optional [alignment] attribute allows to specify the aligment inside the container 6 | /// The optional [style] attribute allows to specify a style (e.g. an Icon) 7 | class CSWidget extends StatelessWidget { 8 | final Widget widget; 9 | final AlignmentGeometry? alignment; 10 | final double height; 11 | final CSWidgetStyle style; 12 | final bool addPaddingToBorder; 13 | final bool showTopBorder; 14 | 15 | const CSWidget( 16 | this.widget, { 17 | this.alignment, 18 | this.height = CS_ITEM_HEIGHT, 19 | this.style = CS_DEFAULT_STYLE, 20 | this.addPaddingToBorder = false, 21 | this.showTopBorder = false, 22 | }); 23 | 24 | @override 25 | Widget build(BuildContext context) { 26 | Widget child; 27 | EdgeInsets padding; 28 | 29 | //style.icon 30 | if (style.icon != null) { 31 | padding = CS_ICON_PADDING; 32 | child = Row( 33 | children: [ 34 | Container( 35 | padding: CS_ICON_PADDING, 36 | child: style.icon, 37 | ), 38 | Expanded(child: widget) 39 | ], 40 | ); 41 | } else { 42 | child = widget; 43 | padding = CS_ITEM_PADDING; 44 | } 45 | 46 | return Container( 47 | alignment: alignment, 48 | decoration: BoxDecoration( 49 | color: CupertinoColors.secondarySystemGroupedBackground 50 | .resolveFrom(context), 51 | border: Border( 52 | top: showTopBorder 53 | ? BorderSide( 54 | color: CupertinoColors.opaqueSeparator.resolveFrom(context), 55 | ) 56 | : BorderSide.none, 57 | ), 58 | ), 59 | constraints: const BoxConstraints(minHeight: 42), 60 | // height: height, 61 | padding: EdgeInsets.only( 62 | left: addPaddingToBorder ? padding.left : 0, 63 | ), 64 | child: Container( 65 | padding: padding.copyWith( 66 | left: addPaddingToBorder ? 2 : padding.left + 2, 67 | ), 68 | decoration: BoxDecoration( 69 | border: Border( 70 | bottom: BorderSide( 71 | color: CupertinoColors.opaqueSeparator.resolveFrom(context), 72 | ), 73 | ), 74 | ), 75 | child: child, 76 | ), 77 | ); 78 | } 79 | } 80 | 81 | /// Defines style attributes that can be applied to every [CSWidget] 82 | class CSWidgetStyle { 83 | final Icon? icon; 84 | 85 | const CSWidgetStyle({this.icon}); 86 | } 87 | 88 | enum ItemType { single, list, listLast } 89 | -------------------------------------------------------------------------------- /packages/flutter_cupertino_settings/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_cupertino_settings 2 | description: Flutter widget to create an iOS settings-table (static TableView). 3 | version: 0.5.0 4 | homepage: https://github.com/matthinc/flutter_cupertino_settings 5 | 6 | environment: 7 | sdk: ">=2.12.0 <3.22.0" 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | cupertino_icons: ^1.0.0 13 | -------------------------------------------------------------------------------- /packages/flutter_cupertino_settings/readme.md: -------------------------------------------------------------------------------- 1 | # flutter_cupertino_settings 2 | 3 | fork by https://github.com/matthinc/flutter_cupertino_settings 4 | 5 | [![Pub badge](https://img.shields.io/pub/v/flutter_cupertino_settings.svg)](https://pub.dartlang.org/packages/flutter_cupertino_settings) ![](https://img.shields.io/github/license/matthinc/flutter_cupertino_settings.svg) 6 | 7 | A Flutter widget to create an iOS settings-table (static TableView). 8 | 9 | ```dart 10 | 11 | import 'package:flutter_cupertino_settings/flutter_cupertino_settings.dart'; 12 | 13 | CSWidgetStyle brightnessStyle = const CSWidgetStyle( 14 | icon: const Icon(Icons.brightness_medium, color: Colors.black54) 15 | ); 16 | 17 | CupertinoSettings( 18 | items: [ 19 | const CSHeader('Brightness'), 20 | CSWidget(CupertinoSlider(value: 0.5), style: brightnessStyle), 21 | CSControl( 22 | nameWidget: Text('Auto brightness'), 23 | contentWidget: CupertinoSwitch(value: true), 24 | style: brightnessStyle, 25 | ), 26 | CSHeader('Selection'), 27 | CSSelection( 28 | items: const >[ 29 | CSSelectionItem(text: 'Day mode', value: 0), 30 | CSSelectionItem(text: 'Night mode', value: 1), 31 | ], 32 | onSelected: (index) {print(index);}, 33 | currentSelection: 0, 34 | ), 35 | CSDescription('Using Night mode extends battery life on devices with OLED display',), 36 | const CSHeader(''), 37 | CSControl( 38 | nameWidget: Text('Loading...'), 39 | contentWidget: CupertinoActivityIndicator(), 40 | ), 41 | CSButton(CSButtonType.DEFAULT, "Licenses", (){ print("It works!"); }), 42 | const CSHeader(''), 43 | CSButton(CSButtonType.DESTRUCTIVE, "Delete all data", (){}) 44 | ] 45 | ); 46 | ``` 47 | 48 | ![](screenshots/scr1.png) 49 | 50 | ### Contributors 51 | - Dark theme & example by [AppleEducate](https://github.com/appleeducate) 52 | - CSSecret by [SimonIT](https://github.com/SimonIT) 53 | - iOS 13 support by [Tim Bierbaum](https://github.com/bierbaumtim) 54 | -------------------------------------------------------------------------------- /packages/simple/lib/intent.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | class ScrollDownIntent extends Intent {} 4 | 5 | class ScrollUpIntent extends Intent {} 6 | 7 | class CategoryNextIntent extends Intent {} 8 | 9 | class CategoryPrevIntent extends Intent {} 10 | -------------------------------------------------------------------------------- /packages/simple/lib/utils.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | const kScrollDuration = Duration(milliseconds: 420); 4 | const kScrollSize = 240; 5 | 6 | scrollUp(ScrollController cx) { 7 | var curr = cx.offset; 8 | if (curr == 0) return; 9 | var exec = curr - kScrollSize; 10 | if (exec < 0) exec = 0; 11 | cx.animateTo(exec, duration: kScrollDuration, curve: Curves.ease); 12 | } 13 | 14 | scrollDown(ScrollController cx) { 15 | var curr = cx.offset; 16 | var max = cx.position.maxScrollExtent; 17 | if (curr == max) return; 18 | var exec = curr + kScrollSize; 19 | if (exec > max) exec = max; 20 | cx.animateTo(exec, duration: kScrollDuration, curve: Curves.ease); 21 | } 22 | -------------------------------------------------------------------------------- /packages/simple/lib/x.dart: -------------------------------------------------------------------------------- 1 | library simple; 2 | 3 | export 'intent.dart'; 4 | export 'utils.dart'; 5 | -------------------------------------------------------------------------------- /packages/simple/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: simple 2 | version: 0.0.1 3 | 4 | environment: 5 | sdk: '>=3.4.0 <4.0.0' 6 | flutter: ">=1.17.0" 7 | 8 | dependencies: 9 | flutter: 10 | sdk: flutter 11 | 12 | dev_dependencies: 13 | flutter_test: 14 | sdk: flutter 15 | flutter_lints: ^3.0.0 -------------------------------------------------------------------------------- /packages/xi/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. 26 | /pubspec.lock 27 | **/doc/api/ 28 | .dart_tool/ 29 | build/ 30 | -------------------------------------------------------------------------------- /packages/xi/README.md: -------------------------------------------------------------------------------- 1 | # xi 2 | 3 | 这个包主要存放一些和爬虫相关的东西 4 | 5 | [](https://civitai.com/images/5353086) 6 | -------------------------------------------------------------------------------- /packages/xi/lib/models/mac_cms/source_data.dart: -------------------------------------------------------------------------------- 1 | import '../../utils/xid.dart'; 2 | 3 | class SourceJsonData { 4 | SourceJsonData({ 5 | this.name, 6 | this.logo, 7 | this.desc, 8 | this.nsfw, 9 | this.api, 10 | this.id, 11 | this.status, 12 | this.jiexiUrl, 13 | }); 14 | 15 | final String? name; 16 | final String? logo; 17 | final String? desc; 18 | final bool? nsfw; 19 | final Api? api; 20 | final String? id; 21 | final bool? status; 22 | final String? jiexiUrl; 23 | 24 | /// [SourceUtils.tryParseData] 25 | @Deprecated('不推荐使用, 推荐使用 SourceUtils.tryParseData()') 26 | factory SourceJsonData.fromJson(Map json) { 27 | var name = json['name']; 28 | var logo = json['logo']; 29 | var desc = json['desc']; 30 | 31 | /// 兼容 `ZY-Player` 32 | var status = json['status'] ?? true; 33 | 34 | var oldID = json['id']; 35 | var id = oldID ?? ""; 36 | if (id.isEmpty) { 37 | var insID = Xid(); 38 | id = insID.toString(); 39 | } 40 | late Api api; 41 | late bool nsfw; 42 | 43 | /// note: 44 | /// => 兼容 `ZY-Player` 的源 45 | /// => 通过判断其是否有 `id` 46 | 47 | bool? _nsfw = json['nsfw']; 48 | 49 | var _api = json['api']; 50 | 51 | if (_api is Map) { 52 | api = Api.fromJson(_api); 53 | } else if (_api is String) { 54 | var url = Uri.tryParse(_api); 55 | if (url != null) { 56 | api = Api( 57 | path: url.path, 58 | root: url.origin, 59 | ); 60 | } 61 | } 62 | 63 | if (_nsfw == null) { 64 | bool flag = json['group'] ?? "" == "18禁"; 65 | nsfw = flag; 66 | } else { 67 | nsfw = _nsfw; 68 | } 69 | 70 | var jiexiUrl = json['jiexiUrl'] ?? ""; 71 | 72 | return SourceJsonData( 73 | name: name, 74 | logo: logo, 75 | desc: desc, 76 | nsfw: nsfw, 77 | api: api, 78 | status: status, 79 | id: id, 80 | jiexiUrl: jiexiUrl, 81 | ); 82 | } 83 | 84 | Map toJson() => { 85 | "name": name, 86 | "logo": logo, 87 | "desc": desc, 88 | "nsfw": nsfw, 89 | "api": api?.toJson(), 90 | 'id': id, 91 | 'status': status, 92 | 'jiexiUrl': jiexiUrl, 93 | }; 94 | } 95 | 96 | class Api { 97 | Api({ 98 | this.root, 99 | this.path, 100 | }); 101 | 102 | final String? root; 103 | final String? path; 104 | 105 | factory Api.fromJson(Map json) => Api( 106 | root: json["root"], 107 | path: json["path"], 108 | ); 109 | 110 | Map toJson() => { 111 | "root": root, 112 | "path": path, 113 | }; 114 | } 115 | -------------------------------------------------------------------------------- /packages/xi/lib/models/models.dart: -------------------------------------------------------------------------------- 1 | export './spec.dart'; 2 | -------------------------------------------------------------------------------- /packages/xi/lib/models/spec.dart: -------------------------------------------------------------------------------- 1 | /// 源列表导入列表, 一般来说是 waifu-project/assets 仓库维护的 .json 文件 2 | class AssetSourceItemJSONData { 3 | /// 源名称 4 | String? title; 5 | 6 | /// 采集地址, 一般是地址合集 7 | String? url; 8 | 9 | /// 源的说明, 一般是导入的时候用来提示的 10 | String? msg; 11 | 12 | /// 是否是 18+ 的源 13 | bool? nsfw; 14 | 15 | AssetSourceItemJSONData({ 16 | this.title, 17 | this.url, 18 | this.msg, 19 | this.nsfw, 20 | }); 21 | 22 | AssetSourceItemJSONData.fromJson(Map json) { 23 | title = json['title']; 24 | url = json['url']; 25 | msg = json['msg']; 26 | nsfw = json['nsfw']; 27 | } 28 | 29 | Map toJson() { 30 | final Map data = {}; 31 | data['title'] = title; 32 | data['url'] = url; 33 | data['msg'] = msg; 34 | data['nsfw'] = nsfw; 35 | return data; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/xi/lib/utils/json.dart: -------------------------------------------------------------------------------- 1 | var MAGIC_START_SYMBOL = [ 2 | "[", 3 | "{", 4 | ]; 5 | 6 | var MAGIC_END_SYMBOL = [ 7 | "]", 8 | "}", 9 | ]; 10 | 11 | enum JSONBodyType { 12 | /// 对象 13 | /// 14 | /// ``` 15 | /// {} 16 | /// ``` 17 | obj, 18 | 19 | /// 数组 20 | /// 21 | /// ``` 22 | /// [] 23 | /// ``` 24 | array, 25 | } 26 | 27 | /// 获取 [json] 的类型 28 | /// 29 | /// 使用 [verifyStringIsJSON] 判断是否是 [json] 字符串 30 | JSONBodyType? getJSONBodyType(String data) { 31 | data = data.trim(); 32 | if (data.startsWith(MAGIC_START_SYMBOL[0])) { 33 | return JSONBodyType.array; 34 | } else if (data.startsWith(MAGIC_START_SYMBOL[1])) { 35 | return JSONBodyType.obj; 36 | } else { 37 | return null; 38 | } 39 | } 40 | 41 | /// 用最二逼的方式校验是否是正确的`json`格式 42 | /// 43 | /// [vJSON] 待校验的json字符串 44 | /// 45 | /// [return] 是否是正确的json格式 46 | bool verifyStringIsJSON(String vJSON) { 47 | var target = vJSON.trim(); 48 | String start = target[0]; 49 | String end = target[target.length - 1]; 50 | return [0, 1].any((index) { 51 | bool startFlag = MAGIC_START_SYMBOL[index] == start; 52 | bool endFlag = MAGIC_END_SYMBOL[index] == end; 53 | return startFlag && endFlag; 54 | }); 55 | } 56 | -------------------------------------------------------------------------------- /packages/xi/lib/utils/maccms.dart: -------------------------------------------------------------------------------- 1 | import '../adapters/mac_cms.dart'; 2 | import '../interface.dart'; 3 | import 'helper.dart'; 4 | 5 | class PlayListData { 6 | final String title; 7 | 8 | final List datas; 9 | 10 | PlayListData({ 11 | required this.title, 12 | required this.datas, 13 | }); 14 | } 15 | 16 | /// 将 [VideoInfo] 转换为 [PlayListData] 17 | /// 单个 [VideoInfo] 格式参考: 18 | /// - name: 源分类集合 19 | /// - url: 多个视频播放地址, 通过 `.split("#").split("$")` 20 | /// > 其中 [0] 为名称, [1] 为视频地址 21 | videoInfo2PlayListData(List cx) { 22 | List result = []; 23 | for (var element in cx) { 24 | var url = element.url; 25 | var hasUrl = isURL(url); 26 | if (hasUrl) { 27 | var output = [element]; 28 | result.add(PlayListData(title: element.name, datas: [])); 29 | var urls = url.split("#"); 30 | if (urls.length >= 2) { 31 | output = urls 32 | .map( 33 | (e) => VideoInfo( 34 | url: e, 35 | type: MacCMSSpider.easyGetVideoType(e), 36 | ), 37 | ) 38 | .toList(); 39 | } 40 | result.last.datas.addAll(output); 41 | } else { 42 | var movies = url.split("#"); 43 | var cache = PlayListData(title: element.name, datas: []); 44 | for (var e in movies) { 45 | var subItem = e.split("\$"); 46 | if (subItem.length <= 1) continue; 47 | var title = subItem[0]; 48 | var url = subItem[1]; 49 | // var subType = subItem[2]; 50 | cache.datas.add(VideoInfo( 51 | name: title, 52 | url: url, 53 | type: MacCMSSpider.easyGetVideoType(url), 54 | )); 55 | } 56 | result.add(cache); 57 | } 58 | } 59 | result = result.where((element) { 60 | return element.datas.isNotEmpty; 61 | }).toList(); 62 | return result; 63 | } 64 | -------------------------------------------------------------------------------- /packages/xi/lib/utils/path.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'package:path_provider/path_provider.dart'; 3 | 4 | ///文件路径工具类 5 | class PathUtils { 6 | PathUtils._internal(); 7 | 8 | ///获取缓存目录路径 9 | static Future getCacheDirPath() async { 10 | Directory directory = await getTemporaryDirectory(); 11 | return directory.path; 12 | } 13 | 14 | ///获取文件缓存目录路径 15 | static Future getFilesDirPath() async { 16 | Directory directory = await getApplicationSupportDirectory(); 17 | return directory.path; 18 | } 19 | 20 | ///获取文档存储目录路径 21 | static Future getDocumentsDirPath() async { 22 | Directory directory = await getApplicationDocumentsDirectory(); 23 | return directory.path; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/xi/lib/utils/utils.dart: -------------------------------------------------------------------------------- 1 | export 'helper.dart'; 2 | export 'http.dart'; 3 | export 'json.dart'; 4 | export 'path.dart'; 5 | export 'source.dart'; 6 | export 'xid.dart'; 7 | export 'maccms.dart'; 8 | -------------------------------------------------------------------------------- /packages/xi/lib/xi.dart: -------------------------------------------------------------------------------- 1 | library xi; 2 | 3 | export 'package:dio/dio.dart'; 4 | export 'package:jsonc/jsonc.dart'; 5 | 6 | export 'interface.dart'; 7 | export 'utils/utils.dart'; 8 | export 'models/models.dart'; 9 | -------------------------------------------------------------------------------- /packages/xi/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: xi 2 | version: 0.0.1 3 | 4 | environment: 5 | sdk: '>=3.4.0 <4.0.0' 6 | flutter: ">=1.17.0" 7 | 8 | dependencies: 9 | flutter: 10 | sdk: flutter 11 | dio: ^5.4.3+1 12 | xml2json: ^6.2.3 13 | cookie_jar: ^4.0.8 14 | dio_cookie_manager: ^3.1.1 15 | awesome_dio_interceptor: ^1.2.0 16 | dio_cache_interceptor: ^3.5.0 17 | path_provider: ^2.1.3 18 | jsonc: ^0.0.3 19 | 20 | dev_dependencies: 21 | flutter_test: 22 | sdk: flutter -------------------------------------------------------------------------------- /packages/xi/test/xi_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | 3 | void main() { 4 | test('xi package test', () { 5 | // noop 6 | }); 7 | } 8 | -------------------------------------------------------------------------------- /schema/README.md: -------------------------------------------------------------------------------- 1 | # Schema 2 | 3 | `asset.json` 是源合集列表格式 4 | 5 | ```json 6 | { 7 | "$schema": "https://raw.githubusercontent.com/waifu-project/movie/dev/schema/assets.json", 8 | "data": [ 9 | { 10 | "title": "源名称", 11 | "url": "采集地址, 一般是地址合集", 12 | "msg": "源的说明, 一般是导入的时候用来提示的", 13 | "nsfw": "是否是 18+ 的源" 14 | } 15 | ] 16 | } 17 | ``` 18 | 19 | `v1.json` 是源列表格式 20 | 21 | ```jsonc 22 | { 23 | "$schema": "https://raw.githubusercontent.com/waifu-project/movie/dev/schema/v1.json", 24 | "data": [ 25 | { 26 | "logo": "图标", 27 | "name": "名称", 28 | "desc": "说明", 29 | "api": { 30 | "root": "根域名", 31 | "path": "路径" 32 | }, 33 | "nsfw": true, 34 | "jiexiUrl": "解析地址", 35 | "id": "id" // 填了没用, 会自动生成id 36 | } 37 | ] 38 | } 39 | ``` -------------------------------------------------------------------------------- /schema/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "properties": { 5 | "data": { 6 | "type": "array", 7 | "items": { 8 | "$ref": "#/definitions/v1" 9 | } 10 | } 11 | }, 12 | "definitions": { 13 | "v1": { 14 | "type": "object", 15 | "properties": { 16 | "title": { 17 | "type": "string", 18 | "description": "源名称" 19 | }, 20 | "url": { 21 | "type": "string", 22 | "description": "采集地址, 一般是地址合集" 23 | }, 24 | "msg": { 25 | "type": "string", 26 | "description": "源的说明, 一般是导入的时候用来提示的" 27 | }, 28 | "nsfw": { 29 | "type": "boolean", 30 | "description": "是否是 18+ 的源" 31 | } 32 | } 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /schema/v1.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "properties": { 5 | "data": { 6 | "type": "array", 7 | "items": { 8 | "$ref": "#/definitions/v1" 9 | } 10 | }, 11 | "mirrors": { 12 | "type": "array", 13 | "items": { 14 | "$ref": "#/definitions/v1" 15 | } 16 | } 17 | }, 18 | "definitions": { 19 | "v1": { 20 | "type": "object", 21 | "properties": { 22 | "logo": { 23 | "type": "string", 24 | "description": "图标" 25 | }, 26 | "name": { 27 | "type": "string", 28 | "description": "名称" 29 | }, 30 | "desc": { 31 | "type": "string", 32 | "description": "说明" 33 | }, 34 | "api": { 35 | "type": "object", 36 | "properties": { 37 | "root": { 38 | "type": "string", 39 | "description": "根域名" 40 | }, 41 | "path": { 42 | "type": "string", 43 | "description": "路径" 44 | } 45 | } 46 | }, 47 | "nsfw": { 48 | "type": "boolean", 49 | "description": "是否是 18+ 的源" 50 | }, 51 | "jiexiUrl": { 52 | "type": "string", 53 | "description": "解析地址" 54 | }, 55 | "id": { 56 | "type": "string", 57 | "description": "id" 58 | } 59 | }, 60 | "required": [ "name", "api", "nsfw" ] 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /script/.gitignore: -------------------------------------------------------------------------------- 1 | y.json -------------------------------------------------------------------------------- /script/add_builtin_yoyo.mjs: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import { execSync } from 'child_process' 3 | 4 | function wget(url, path) { 5 | const cmd = `wget ${url} -O ${path}` 6 | console.log(cmd) 7 | execSync(cmd) 8 | } 9 | 10 | // https://stackoverflow.com/a/1349426 11 | function makeid(length) { 12 | let result = ''; 13 | const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 14 | const charactersLength = characters.length; 15 | let counter = 0; 16 | while (counter < length) { 17 | result += characters.charAt(Math.floor(Math.random() * charactersLength)); 18 | counter += 1; 19 | } 20 | return result; 21 | } 22 | 23 | 24 | ;(async ()=> { 25 | // console.log("该脚本会自动将社区维护的 yoyo.json 添加到内建支持中") 26 | const yoyoJSONFile = 'y.json' 27 | if (!fs.existsSync(yoyoJSONFile)) { 28 | wget('https://cdn.jsdelivr.net/gh/waifu-project/v1@latest/yoyo.json', yoyoJSONFile) 29 | } 30 | /** @type {Array} */ 31 | const data = JSON.parse(fs.readFileSync(yoyoJSONFile).toString('utf8')) 32 | let codegen = `import 'package:xi/adapters/mac_cms.dart';\n\n` 33 | codegen += 'var list$ = [\n' 34 | const p = `MacCMSSpider` 35 | data.forEach(item=> { 36 | const id = makeid(9) 37 | const line = ` ${p}(name: "${item.name}", root_url: "${item.api.root}", api_path: "${item.api.path}", nsfw: ${item.nsfw}, id: "${id}", status: true),\n` 38 | codegen += line 39 | }) 40 | codegen += '];\n' 41 | 42 | const file1 = "../lib/builtin/maccms/maccms.dart" 43 | const file2 = "../lib/isar/schema/settings_schema.dart" 44 | if (!fs.existsSync(file1) || !fs.existsSync(file2)) { 45 | throw new Error("操作文件不存在") 46 | } 47 | fs.writeFileSync(file1, codegen) 48 | 49 | // default enable nsfw 50 | execSync(`sed -i '' 's/isNSFW = false/isNSFW = true/' ${file2}`) 51 | })() 52 | -------------------------------------------------------------------------------- /script/bundle-ios: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | 3 | flutter build ios --release --no-codesign 4 | cd build/ios/iphoneos 5 | mkdir Payload 6 | cd Payload 7 | ln -s ../Runner.app 8 | cd .. 9 | zip -r yoyo.ipa Payload -------------------------------------------------------------------------------- /script/bundle-mac: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | 3 | echo "start build yoyo.app" 4 | flutter build macos --release 5 | echo "cp yoyo.app to /Applications" 6 | cp -rf build/macos/Build/Products/Release/yoyo.app /Applications -------------------------------------------------------------------------------- /script/ckbot/.gitignore: -------------------------------------------------------------------------------- 1 | output.json 2 | porn.txt 3 | __debug_bin* 4 | output.html -------------------------------------------------------------------------------- /script/ckbot/README.md: -------------------------------------------------------------------------------- 1 | # check-bot 2 | 3 | 该脚本用于检查源合集是否可用 4 | 5 | 资源收集贴: https://github.com/waifu-project/movie/issues/45 -------------------------------------------------------------------------------- /script/ckbot/go.mod: -------------------------------------------------------------------------------- 1 | module d1y.io/movie 2 | 3 | go 1.22.4 4 | 5 | require ( 6 | github.com/charmbracelet/log v0.4.0 7 | github.com/imroc/req/v3 v3.43.7 8 | github.com/sourcegraph/conc v0.3.0 9 | ) 10 | 11 | require ( 12 | github.com/andybalholm/brotli v1.1.0 // indirect 13 | github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect 14 | github.com/charmbracelet/lipgloss v0.10.0 // indirect 15 | github.com/cloudflare/circl v1.3.7 // indirect 16 | github.com/go-logfmt/logfmt v0.6.0 // indirect 17 | github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect 18 | github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 // indirect 19 | github.com/hashicorp/errwrap v1.1.0 // indirect 20 | github.com/hashicorp/go-multierror v1.1.1 // indirect 21 | github.com/klauspost/compress v1.17.7 // indirect 22 | github.com/lucasb-eyer/go-colorful v1.2.0 // indirect 23 | github.com/mattn/go-isatty v0.0.18 // indirect 24 | github.com/mattn/go-runewidth v0.0.15 // indirect 25 | github.com/muesli/reflow v0.3.0 // indirect 26 | github.com/muesli/termenv v0.15.2 // indirect 27 | github.com/onsi/ginkgo/v2 v2.16.0 // indirect 28 | github.com/quic-go/qpack v0.4.0 // indirect 29 | github.com/quic-go/quic-go v0.41.0 // indirect 30 | github.com/refraction-networking/utls v1.6.3 // indirect 31 | github.com/rivo/uniseg v0.4.7 // indirect 32 | go.uber.org/atomic v1.7.0 // indirect 33 | go.uber.org/mock v0.4.0 // indirect 34 | go.uber.org/multierr v1.9.0 // indirect 35 | golang.org/x/crypto v0.21.0 // indirect 36 | golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect 37 | golang.org/x/mod v0.16.0 // indirect 38 | golang.org/x/net v0.22.0 // indirect 39 | golang.org/x/sys v0.18.0 // indirect 40 | golang.org/x/text v0.14.0 // indirect 41 | golang.org/x/tools v0.19.0 // indirect 42 | ) 43 | -------------------------------------------------------------------------------- /script/create_schema.mjs: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | 3 | ;(()=> { 4 | const spec = fs.readFileSync("packages/xi/lib/models/spec.dart").toString("utf8").split("\n").map(item=> item.trim()) 5 | // delete first line 6 | spec.shift() 7 | /** @type {Record} */ 8 | const v1 = {} 9 | for (let i = 0; i < spec.length; i++) { 10 | const line = spec[i] 11 | if (line.startsWith("///")) { 12 | const desc = line.replace("///", "").trim() 13 | const [ _type, _key ] = spec[i + 1].split(" ") 14 | const key = _key.replace(";", "") 15 | let type = _type.replace("?", "") 16 | if (type == "String") { 17 | type = "string" 18 | } else if (type == "bool") { 19 | type = "boolean" 20 | } else if (type == "int") { 21 | type = "number" 22 | } 23 | v1[key] = { 24 | type, 25 | description: desc, 26 | } 27 | } 28 | } 29 | const cx = { 30 | $schema: "http://json-schema.org/draft-07/schema#", 31 | type: "object", 32 | properties: { 33 | data: { 34 | type: "array", 35 | items: { 36 | $ref: "#/definitions/v1" 37 | } 38 | } 39 | }, 40 | definitions: { 41 | v1: { 42 | type: "object", 43 | properties: v1, 44 | }, 45 | }, 46 | } 47 | fs.writeFileSync("schema/assets.json", JSON.stringify(cx, null, 2)) 48 | })() -------------------------------------------------------------------------------- /script/draft-release-notes.js: -------------------------------------------------------------------------------- 1 | const execSync = require('child_process').execSync 2 | 3 | const noteReg = /Release Notes:([\s\S]+)/ 4 | 5 | // git show format spec: https://git-scm.com/docs/git-show#_pretty_formats 6 | /** @param {string} hash */ 7 | function getCommitBody(hash) { 8 | const body = execSync(`git show ${hash} --stat=0 --no-patch --format="%b"`).toString('utf-8').trim() 9 | return body 10 | } 11 | 12 | /** 13 | * @param {string} body 14 | * @returns {string[] | null} 15 | */ 16 | function parseCommitBody(body) { 17 | if (!body) return null 18 | const cx = body.match(noteReg) 19 | if (!cx) return null 20 | const [ , notes ] = cx 21 | if (!notes) return null 22 | /** @type {string[]} */ 23 | const result = notes.trim().split("\n").map(item=> { 24 | const _ = item.trim() 25 | if (!_.startsWith("-")) return null 26 | return _.replace(/^- /, "") 27 | }).filter(Boolean) 28 | if (!result.length) return null 29 | return result 30 | } 31 | 32 | /** 33 | * @param {string} a 34 | * @param {string} b 35 | * @returns 36 | */ 37 | function getTwoTagCommitHashs(a, b) { 38 | return execSync(`git log --oneline --format="%h" ${a}...${b}`).toString('utf-8').trim().split("\n") 39 | } 40 | 41 | function getLatestTags(size = 2) { 42 | return execSync(`git tag -l --sort=-v:refname | head -${size}`).toString('utf-8').trim().split("\n") 43 | } 44 | 45 | /** 46 | * @param {string} tag 47 | */ 48 | function getTagNote(tag) { 49 | const _ = execSync(`git show ${tag} --stat=0 --no-patch --format="%N"`).toString('utf-8').trim() 50 | const note = _.split("\n").filter(item=> { return !!item.trim() }) 51 | // 第一行第二行不需要 52 | note.shift() 53 | note.shift() 54 | return note.join("\n") + "\n" 55 | } 56 | 57 | ;(async()=> { 58 | const repo = "waifu-project/movie" 59 | const token = process.env.GITHUB_TOKEN 60 | const resp = await fetch(`https://api.github.com/repos/${repo}/tags`, { 61 | headers: { 62 | "Authorization": `Bearer ${token}` 63 | } 64 | }) 65 | /** @type {GithubTagResponse} */ 66 | const tags = await resp.json() 67 | const now = tags[0].name 68 | const old = tags[1].name//我赌你枪里没有子弹 69 | // const tags = getLatestTags() 70 | const hashs = getTwoTagCommitHashs(now, old) 71 | let notes = [] 72 | for (const hash of hashs) { 73 | const body = getCommitBody(hash) 74 | const _ = parseCommitBody(body) 75 | if (_) { 76 | notes = [...notes, ..._] 77 | } 78 | } 79 | let releaseNote = getTagNote(now) 80 | releaseNote += notes.map(item=> `- ${item}`).join("\n") 81 | console.log(releaseNote) 82 | })() -------------------------------------------------------------------------------- /script/fetch_git_info.ps1: -------------------------------------------------------------------------------- 1 | $FILE = "lib/git_info.dart" 2 | 3 | $COMMIT = git rev-parse --short HEAD 4 | $DESCRIBE = git describe --tags --always 5 | 6 | # copy by ChatGPT 7 | 8 | # copy by https://gist.github.com/ericbmerritt/f52f1c48b86150704270 9 | # https://gist.github.com/rponte/fdc0724dd984088606b0 10 | 11 | # increment the build number (ie 115 to 116) 12 | $VERSION = ($DESCRIBE -split '-')[0] 13 | $BUILD = ($DESCRIBE -split '-')[1] 14 | $PATCH = ($DESCRIBE -split '-')[2] 15 | 16 | if ($DESCRIBE -match '^[A-Fa-f0-9]+$') { 17 | $VERSION = "0.0.0" 18 | $BUILD = $(git rev-list HEAD --count) 19 | $PATCH = $DESCRIBE 20 | } 21 | 22 | if (-not $BUILD) { 23 | $BUILD = '0' 24 | } 25 | 26 | if (-not $PATCH) { 27 | $PATCH = $DESCRIBE 28 | } 29 | 30 | $REAL_VERSION = "$BUILD.$PATCH" 31 | Set-Content -Path $FILE -Value "const gitCommit = '$COMMIT';`nconst gitTag = '$REAL_VERSION';" 32 | -------------------------------------------------------------------------------- /script/fetch_git_info.sh: -------------------------------------------------------------------------------- 1 | FILE="lib/git_info.dart" 2 | 3 | COMMIT=`git rev-parse --short HEAD` 4 | DESCRIBE=`git describe --tags --always` 5 | 6 | # copy by https://gist.github.com/ericbmerritt/f52f1c48b86150704270 7 | # https://gist.github.com/rponte/fdc0724dd984088606b0 8 | 9 | # increment the build number (ie 115 to 116) 10 | # VERSION=`echo $DESCRIBE | awk '{split($0,a,"-"); print a[1]}'` 11 | BUILD=`echo $DESCRIBE | awk '{split($0,a,"-"); print a[2]}'` 12 | PATCH=`echo $DESCRIBE | awk '{split($0,a,"-"); print a[3]}'` 13 | 14 | if [[ "${DESCRIBE}" =~ ^[A-Fa-f0-9]+$ ]]; then 15 | # VERSION="0.0.0" 16 | BUILD=`git rev-list HEAD --count` 17 | PATCH=${DESCRIBE} 18 | fi 19 | 20 | if [ "${BUILD}" = "" ]; then 21 | BUILD='0' 22 | fi 23 | 24 | if [ "${BUILD}" = "" ]; then 25 | PATCH=$DESCRIBE 26 | fi 27 | 28 | 29 | REAL_VERSION=${BUILD}.${PATCH} 30 | echo "const gitCommit = '$COMMIT';" > $FILE 31 | echo "const gitTag = '$REAL_VERSION';" >> $FILE -------------------------------------------------------------------------------- /script/linux_apply_font.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import re 3 | 4 | # copy by ChatGPT 5 | 6 | with subprocess.Popen(['wget', '-O', 'fonts/LXG.ttf', 'https://github.com/lxgw/LxgwWenKai/releases/latest/download/LXGWWenKai-Regular.ttf'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) as p: 7 | for line in p.stdout: 8 | print(line) 9 | 10 | fontConfig = """ 11 | fonts: 12 | - family: LXG 13 | fonts: 14 | - asset: fonts/LXG.ttf 15 | 16 | """ 17 | 18 | with open('pubspec.yaml', 'r') as f: 19 | file_content = f.read() 20 | file_content = re.sub(r'##HERE\n(.*\n)*\n', fontConfig, file_content) 21 | print('replace success') 22 | 23 | with open('pubspec.yaml', 'w') as f: 24 | f.write(file_content) -------------------------------------------------------------------------------- /script/patch.d.ts: -------------------------------------------------------------------------------- 1 | interface Tag { 2 | name: string 3 | } 4 | 5 | type GithubTagResponse = Array 6 | 7 | interface SourceItem { 8 | name: string 9 | nsfw: boolean 10 | api: { 11 | root: string 12 | path: string 13 | } 14 | } -------------------------------------------------------------------------------- /test/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/test/.gitkeep -------------------------------------------------------------------------------- /windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral/ 2 | 3 | # Visual Studio user-specific files. 4 | *.suo 5 | *.user 6 | *.userosscache 7 | *.sln.docstates 8 | 9 | # Visual Studio build-related files. 10 | x64/ 11 | x86/ 12 | 13 | # Visual Studio cache files 14 | # files ending in .cache can be ignored 15 | *.[Cc]ache 16 | # but keep track of directories ending in .cache 17 | !*.[Cc]ache/ 18 | -------------------------------------------------------------------------------- /windows/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | void RegisterPlugins(flutter::PluginRegistry* registry) { 19 | BitsdojoWindowPluginRegisterWithRegistrar( 20 | registry->GetRegistrarForPlugin("BitsdojoWindowPlugin")); 21 | DesktopWebviewWindowPluginRegisterWithRegistrar( 22 | registry->GetRegistrarForPlugin("DesktopWebviewWindowPlugin")); 23 | IsarFlutterLibsPluginRegisterWithRegistrar( 24 | registry->GetRegistrarForPlugin("IsarFlutterLibsPlugin")); 25 | ProtocolHandlerWindowsPluginCApiRegisterWithRegistrar( 26 | registry->GetRegistrarForPlugin("ProtocolHandlerWindowsPluginCApi")); 27 | ScreenRetrieverPluginRegisterWithRegistrar( 28 | registry->GetRegistrarForPlugin("ScreenRetrieverPlugin")); 29 | SharePlusWindowsPluginCApiRegisterWithRegistrar( 30 | registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); 31 | UrlLauncherWindowsRegisterWithRegistrar( 32 | registry->GetRegistrarForPlugin("UrlLauncherWindows")); 33 | WindowManagerPluginRegisterWithRegistrar( 34 | registry->GetRegistrarForPlugin("WindowManagerPlugin")); 35 | } 36 | -------------------------------------------------------------------------------- /windows/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void RegisterPlugins(flutter::PluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /windows/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | bitsdojo_window_windows 7 | desktop_webview_window 8 | isar_flutter_libs 9 | protocol_handler_windows 10 | screen_retriever 11 | share_plus 12 | url_launcher_windows 13 | window_manager 14 | ) 15 | 16 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 17 | ) 18 | 19 | set(PLUGIN_BUNDLED_LIBRARIES) 20 | 21 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 22 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) 23 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 24 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 25 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 26 | endforeach(plugin) 27 | 28 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 29 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) 30 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 31 | endforeach(ffi_plugin) 32 | -------------------------------------------------------------------------------- /windows/runner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(runner LANGUAGES CXX) 3 | 4 | add_executable(${BINARY_NAME} WIN32 5 | "flutter_window.cpp" 6 | "main.cpp" 7 | "utils.cpp" 8 | "win32_window.cpp" 9 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 10 | "Runner.rc" 11 | "runner.exe.manifest" 12 | ) 13 | apply_standard_settings(${BINARY_NAME}) 14 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") 15 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) 16 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") 17 | add_dependencies(${BINARY_NAME} flutter_assemble) 18 | -------------------------------------------------------------------------------- /windows/runner/Runner.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #pragma code_page(65001) 4 | #include "resource.h" 5 | 6 | #define APSTUDIO_READONLY_SYMBOLS 7 | ///////////////////////////////////////////////////////////////////////////// 8 | // 9 | // Generated from the TEXTINCLUDE 2 resource. 10 | // 11 | #include "winres.h" 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | #undef APSTUDIO_READONLY_SYMBOLS 15 | 16 | ///////////////////////////////////////////////////////////////////////////// 17 | // English (United States) resources 18 | 19 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""winres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "\r\n" 42 | "\0" 43 | END 44 | 45 | #endif // APSTUDIO_INVOKED 46 | 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | // 50 | // Icon 51 | // 52 | 53 | // Icon with lowest ID value placed first to ensure application icon 54 | // remains consistent on all systems. 55 | IDI_APP_ICON ICON "resources\\app_icon.ico" 56 | 57 | 58 | ///////////////////////////////////////////////////////////////////////////// 59 | // 60 | // Version 61 | // 62 | 63 | #ifdef FLUTTER_BUILD_NUMBER 64 | #define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER 65 | #else 66 | #define VERSION_AS_NUMBER 1,0,0 67 | #endif 68 | 69 | #ifdef FLUTTER_BUILD_NAME 70 | #define VERSION_AS_STRING #FLUTTER_BUILD_NAME 71 | #else 72 | #define VERSION_AS_STRING "1.0.0" 73 | #endif 74 | 75 | VS_VERSION_INFO VERSIONINFO 76 | FILEVERSION VERSION_AS_NUMBER 77 | PRODUCTVERSION VERSION_AS_NUMBER 78 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK 79 | #ifdef _DEBUG 80 | FILEFLAGS VS_FF_DEBUG 81 | #else 82 | FILEFLAGS 0x0L 83 | #endif 84 | FILEOS VOS__WINDOWS32 85 | FILETYPE VFT_APP 86 | FILESUBTYPE 0x0L 87 | BEGIN 88 | BLOCK "StringFileInfo" 89 | BEGIN 90 | BLOCK "040904e4" 91 | BEGIN 92 | VALUE "CompanyName", "io.github.d1y.movie" "\0" 93 | VALUE "FileDescription", "A new Flutter project." "\0" 94 | VALUE "FileVersion", VERSION_AS_STRING "\0" 95 | VALUE "InternalName", "movie" "\0" 96 | VALUE "LegalCopyright", "Copyright (C) 2021-2022 io.github.d1y.movie. All rights reserved." "\0" 97 | VALUE "OriginalFilename", "movie.exe" "\0" 98 | VALUE "ProductName", "movie" "\0" 99 | VALUE "ProductVersion", VERSION_AS_STRING "\0" 100 | END 101 | END 102 | BLOCK "VarFileInfo" 103 | BEGIN 104 | VALUE "Translation", 0x409, 1252 105 | END 106 | END 107 | 108 | #endif // English (United States) resources 109 | ///////////////////////////////////////////////////////////////////////////// 110 | 111 | 112 | 113 | #ifndef APSTUDIO_INVOKED 114 | ///////////////////////////////////////////////////////////////////////////// 115 | // 116 | // Generated from the TEXTINCLUDE 3 resource. 117 | // 118 | 119 | 120 | ///////////////////////////////////////////////////////////////////////////// 121 | #endif // not APSTUDIO_INVOKED 122 | -------------------------------------------------------------------------------- /windows/runner/flutter_window.cpp: -------------------------------------------------------------------------------- 1 | #include "flutter_window.h" 2 | 3 | #include 4 | 5 | #include "flutter/generated_plugin_registrant.h" 6 | 7 | FlutterWindow::FlutterWindow(const flutter::DartProject& project) 8 | : project_(project) {} 9 | 10 | FlutterWindow::~FlutterWindow() {} 11 | 12 | bool FlutterWindow::OnCreate() { 13 | if (!Win32Window::OnCreate()) { 14 | return false; 15 | } 16 | 17 | RECT frame = GetClientArea(); 18 | 19 | // The size here must match the window dimensions to avoid unnecessary surface 20 | // creation / destruction in the startup path. 21 | flutter_controller_ = std::make_unique( 22 | frame.right - frame.left, frame.bottom - frame.top, project_); 23 | // Ensure that basic setup of the controller was successful. 24 | if (!flutter_controller_->engine() || !flutter_controller_->view()) { 25 | return false; 26 | } 27 | RegisterPlugins(flutter_controller_->engine()); 28 | SetChildContent(flutter_controller_->view()->GetNativeWindow()); 29 | // Flutter can complete the first frame before the "show window" callback is 30 | // registered. The following call ensures a frame is pending to ensure the 31 | // window is shown. It is a no-op if the first frame hasn't completed yet. 32 | // ref https://docs.flutter.dev/release/breaking-changes/windows-show-window-migration 33 | flutter_controller_->ForceRedraw(); 34 | return true; 35 | } 36 | 37 | void FlutterWindow::OnDestroy() { 38 | if (flutter_controller_) { 39 | flutter_controller_ = nullptr; 40 | } 41 | 42 | Win32Window::OnDestroy(); 43 | } 44 | 45 | LRESULT 46 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message, 47 | WPARAM const wparam, 48 | LPARAM const lparam) noexcept { 49 | // Give Flutter, including plugins, an opportunity to handle window messages. 50 | if (flutter_controller_) { 51 | std::optional result = 52 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, 53 | lparam); 54 | if (result) { 55 | return *result; 56 | } 57 | } 58 | 59 | switch (message) { 60 | case WM_FONTCHANGE: 61 | flutter_controller_->engine()->ReloadSystemFonts(); 62 | break; 63 | } 64 | 65 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam); 66 | } 67 | -------------------------------------------------------------------------------- /windows/runner/flutter_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_FLUTTER_WINDOW_H_ 2 | #define RUNNER_FLUTTER_WINDOW_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "win32_window.h" 10 | 11 | // A window that does nothing but host a Flutter view. 12 | class FlutterWindow : public Win32Window { 13 | public: 14 | // Creates a new FlutterWindow hosting a Flutter view running |project|. 15 | explicit FlutterWindow(const flutter::DartProject& project); 16 | virtual ~FlutterWindow(); 17 | 18 | protected: 19 | // Win32Window: 20 | bool OnCreate() override; 21 | void OnDestroy() override; 22 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, 23 | LPARAM const lparam) noexcept override; 24 | 25 | private: 26 | // The project to run. 27 | flutter::DartProject project_; 28 | 29 | // The Flutter instance hosted by this window. 30 | std::unique_ptr flutter_controller_; 31 | }; 32 | 33 | #endif // RUNNER_FLUTTER_WINDOW_H_ 34 | -------------------------------------------------------------------------------- /windows/runner/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | auto bdw = bitsdojo_window_configure(BDW_CUSTOM_FRAME | BDW_HIDE_ON_STARTUP); 7 | 8 | #include "flutter_window.h" 9 | #include "utils.h" 10 | 11 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, 12 | _In_ wchar_t *command_line, _In_ int show_command) { 13 | 14 | // Replace protocol_handler_example with your_window_title. 15 | HWND hwnd = ::FindWindow(L"FLUTTER_RUNNER_WIN32_WINDOW", L"yoyo"); 16 | if (hwnd != NULL) { 17 | DispatchToProtocolHandler(hwnd); 18 | ::ShowWindow(hwnd, SW_NORMAL); 19 | ::SetForegroundWindow(hwnd); 20 | return EXIT_FAILURE; 21 | } 22 | 23 | // Attach to console when present (e.g., 'flutter run') or create a 24 | // new console when running with a debugger. 25 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { 26 | CreateAndAttachConsole(); 27 | } 28 | 29 | // Initialize COM, so that it is available for use in the library and/or 30 | // plugins. 31 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); 32 | 33 | flutter::DartProject project(L"data"); 34 | 35 | std::vector command_line_arguments = 36 | GetCommandLineArguments(); 37 | 38 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); 39 | 40 | FlutterWindow window(project); 41 | Win32Window::Point origin(10, 10); 42 | Win32Window::Size size(1280, 720); 43 | if (!window.CreateAndShow(L"movie", origin, size)) { 44 | return EXIT_FAILURE; 45 | } 46 | window.SetQuitOnClose(true); 47 | 48 | ::MSG msg; 49 | while (::GetMessage(&msg, nullptr, 0, 0)) { 50 | ::TranslateMessage(&msg); 51 | ::DispatchMessage(&msg); 52 | } 53 | 54 | ::CoUninitialize(); 55 | return EXIT_SUCCESS; 56 | } 57 | -------------------------------------------------------------------------------- /windows/runner/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Runner.rc 4 | // 5 | #define IDI_APP_ICON 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /windows/runner/resources/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waifu-project/movie/62b0b07e1d19965220791e1e495142550e76437d/windows/runner/resources/app_icon.ico -------------------------------------------------------------------------------- /windows/runner/runner.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PerMonitorV2 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /windows/runner/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | void CreateAndAttachConsole() { 11 | if (::AllocConsole()) { 12 | FILE *unused; 13 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) { 14 | _dup2(_fileno(stdout), 1); 15 | } 16 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) { 17 | _dup2(_fileno(stdout), 2); 18 | } 19 | std::ios::sync_with_stdio(); 20 | FlutterDesktopResyncOutputStreams(); 21 | } 22 | } 23 | 24 | std::vector GetCommandLineArguments() { 25 | // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. 26 | int argc; 27 | wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); 28 | if (argv == nullptr) { 29 | return std::vector(); 30 | } 31 | 32 | std::vector command_line_arguments; 33 | 34 | // Skip the first argument as it's the binary name. 35 | for (int i = 1; i < argc; i++) { 36 | command_line_arguments.push_back(Utf8FromUtf16(argv[i])); 37 | } 38 | 39 | ::LocalFree(argv); 40 | 41 | return command_line_arguments; 42 | } 43 | 44 | std::string Utf8FromUtf16(const wchar_t* utf16_string) { 45 | if (utf16_string == nullptr) { 46 | return std::string(); 47 | } 48 | int target_length = ::WideCharToMultiByte( 49 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 50 | -1, nullptr, 0, nullptr, nullptr); 51 | if (target_length == 0) { 52 | return std::string(); 53 | } 54 | std::string utf8_string; 55 | utf8_string.resize(target_length); 56 | int converted_length = ::WideCharToMultiByte( 57 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 58 | -1, utf8_string.data(), 59 | target_length, nullptr, nullptr); 60 | if (converted_length == 0) { 61 | return std::string(); 62 | } 63 | return utf8_string; 64 | } 65 | -------------------------------------------------------------------------------- /windows/runner/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_UTILS_H_ 2 | #define RUNNER_UTILS_H_ 3 | 4 | #include 5 | #include 6 | 7 | // Creates a console for the process, and redirects stdout and stderr to 8 | // it for both the runner and the Flutter library. 9 | void CreateAndAttachConsole(); 10 | 11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string 12 | // encoded in UTF-8. Returns an empty std::string on failure. 13 | std::string Utf8FromUtf16(const wchar_t* utf16_string); 14 | 15 | // Gets the command line arguments passed in as a std::vector, 16 | // encoded in UTF-8. Returns an empty std::vector on failure. 17 | std::vector GetCommandLineArguments(); 18 | 19 | #endif // RUNNER_UTILS_H_ 20 | --------------------------------------------------------------------------------