├── .env_example ├── .gitignore ├── .metadata ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── analysis_options.yaml ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── io │ │ │ │ └── flutter │ │ │ │ └── app │ │ │ │ └── FlutterMultiDexApplication.java │ │ ├── kotlin │ │ │ └── app │ │ │ │ └── animestream │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable-hdpi │ │ │ ├── android12splash.png │ │ │ ├── ic_launcher_background.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── splash.png │ │ │ ├── drawable-mdpi │ │ │ ├── android12splash.png │ │ │ ├── ic_launcher_background.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── splash.png │ │ │ ├── drawable-night-hdpi │ │ │ ├── android12splash.png │ │ │ └── splash.png │ │ │ ├── drawable-night-mdpi │ │ │ ├── android12splash.png │ │ │ └── splash.png │ │ │ ├── drawable-night-v21 │ │ │ ├── background.png │ │ │ └── launch_background.xml │ │ │ ├── drawable-night-xhdpi │ │ │ ├── android12splash.png │ │ │ └── splash.png │ │ │ ├── drawable-night-xxhdpi │ │ │ ├── android12splash.png │ │ │ └── splash.png │ │ │ ├── drawable-night-xxxhdpi │ │ │ ├── android12splash.png │ │ │ └── splash.png │ │ │ ├── drawable-night │ │ │ ├── background.png │ │ │ └── launch_background.xml │ │ │ ├── drawable-v21 │ │ │ ├── background.png │ │ │ └── launch_background.xml │ │ │ ├── drawable-xhdpi │ │ │ ├── android12splash.png │ │ │ ├── ic_launcher_background.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── splash.png │ │ │ ├── drawable-xxhdpi │ │ │ ├── android12splash.png │ │ │ ├── ic_launcher_background.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── splash.png │ │ │ ├── drawable-xxxhdpi │ │ │ ├── android12splash.png │ │ │ ├── ic_launcher_background.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── splash.png │ │ │ ├── drawable │ │ │ ├── background.png │ │ │ ├── banner.png │ │ │ └── launch_background.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ └── ic_launcher.xml │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── values-night-v31 │ │ │ └── styles.xml │ │ │ ├── values-night │ │ │ └── styles.xml │ │ │ ├── values-v31 │ │ │ └── styles.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ └── styles.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── changelog.md ├── devtools_options.yaml ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── 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 │ │ │ └── darkbackground.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ ├── LaunchImageDark.png │ │ │ ├── LaunchImageDark@2x.png │ │ │ ├── LaunchImageDark@3x.png │ │ │ └── README.md │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h └── RunnerTests │ └── RunnerTests.swift ├── lib ├── assets │ ├── fonts │ │ ├── ARIAL.TTF │ │ ├── ARIALBD.TTF │ │ ├── Helvetica-Bold.ttf │ │ ├── Helvetica.ttf │ │ ├── NotoSans-Bold.ttf │ │ ├── NotoSans-Regular.ttf │ │ ├── NunitoSans_10pt-Bold.ttf │ │ ├── NunitoSans_10pt-Medium.ttf │ │ ├── Poppins-Bold.ttf │ │ ├── Rubik-Bold.ttf │ │ └── Rubik-Medium.ttf │ ├── icons │ │ ├── logo.png │ │ ├── logo_background.png │ │ ├── logo_foreground.png │ │ ├── logo_foreground_splash.png │ │ └── logo_monochrome.png │ └── images │ │ ├── broken_heart.png │ │ ├── check.png │ │ ├── chisato.jpeg │ │ ├── chisato_AI.jpg │ │ ├── ghost.png │ │ ├── mitsuha.jpg │ │ ├── profile_banner.jpg │ │ └── search.png ├── core │ ├── anime │ │ ├── downloader │ │ │ ├── downloader.dart │ │ │ └── types.dart │ │ ├── extractors │ │ │ ├── kwik.dart │ │ │ ├── streamwish.dart │ │ │ └── type.dart │ │ └── providers │ │ │ ├── animeProvider.dart │ │ │ ├── animeonsen.dart │ │ │ ├── animepahe.dart │ │ │ ├── aniplay.dart │ │ │ ├── apRemote.dart │ │ │ ├── bridge.dart │ │ │ ├── gojo.dart │ │ │ ├── providerDetails.dart │ │ │ ├── providerManager.dart │ │ │ ├── providerPlugin.dart │ │ │ ├── registers │ │ │ ├── html.dart │ │ │ └── http.dart │ │ │ └── types.dart │ ├── app │ │ ├── logging.dart │ │ ├── runtimeDatas.dart │ │ └── update.dart │ ├── commons │ │ ├── enums.dart │ │ ├── extractQuality.dart │ │ ├── genresAndTags.dart │ │ ├── subtitleParsers.dart │ │ ├── types.dart │ │ └── utils.dart │ ├── data │ │ ├── animeSpecificPreference.dart │ │ ├── hive.dart │ │ ├── misc.dart │ │ ├── preferences.dart │ │ ├── providers.dart │ │ ├── secureStorage.dart │ │ ├── settings.dart │ │ ├── theme.dart │ │ ├── types.dart │ │ └── watching.dart │ ├── database │ │ ├── anilist │ │ │ ├── anilist.dart │ │ │ ├── login.dart │ │ │ ├── mutations.dart │ │ │ ├── queries.dart │ │ │ └── types.dart │ │ ├── database.dart │ │ ├── handler │ │ │ ├── handler.dart │ │ │ └── syncHandler.dart │ │ ├── mal │ │ │ ├── login.dart │ │ │ ├── mal.dart │ │ │ ├── mutations.dart │ │ │ └── types.dart │ │ ├── simkl │ │ │ ├── login.dart │ │ │ ├── mutations.dart │ │ │ ├── simkl.dart │ │ │ └── types.dart │ │ └── types.dart │ └── news │ │ └── animenews.dart ├── main.dart └── ui │ ├── models │ ├── bottomSheets │ │ ├── customControlsSheet.dart │ │ ├── manualSearchSheet.dart │ │ ├── mediaListStatus.dart │ │ └── serverSelectionSheet.dart │ ├── extensions.dart │ ├── notification.dart │ ├── providers │ │ ├── infoProvider.dart │ │ ├── playerDataProvider.dart │ │ ├── playerProvider.dart │ │ └── themeProvider.dart │ ├── snackBar.dart │ ├── sources.dart │ ├── watchPageUtil.dart │ └── widgets │ │ ├── ContextMenu.dart │ │ ├── appWrapper.dart │ │ ├── bottomBar.dart │ │ ├── cards.dart │ │ ├── cards │ │ ├── animeCard.dart │ │ └── animeCardExtended.dart │ │ ├── clickableItem.dart │ │ ├── header.dart │ │ ├── infoPageWidgets │ │ ├── commonInfo.dart │ │ ├── continueBoxes.dart │ │ ├── episodeGrid.dart │ │ ├── infoSection.dart │ │ ├── scrollingList.dart │ │ ├── sourceBoxes.dart │ │ └── watchSection.dart │ │ ├── loader.dart │ │ ├── navRail.dart │ │ ├── player │ │ ├── customControls.dart │ │ ├── desktopControls.dart │ │ └── playerUtils.dart │ │ ├── slider.dart │ │ ├── sourceTile.dart │ │ ├── subtitles │ │ ├── subViewer.dart │ │ ├── subtitle.dart │ │ ├── subtitleSettings.dart │ │ └── subtitleText.dart │ │ └── toggleItem.dart │ ├── pages │ ├── Discover.dart │ ├── genres.dart │ ├── home.dart │ ├── info.dart │ ├── info │ │ ├── infoDesktop.dart │ │ └── infoMobile.dart │ ├── lists.dart │ ├── mainNav.dart │ ├── news.dart │ ├── newsDetail.dart │ ├── search.dart │ ├── settingPages │ │ ├── account.dart │ │ ├── appInfo.dart │ │ ├── common.dart │ │ ├── general.dart │ │ ├── player.dart │ │ ├── plugin.dart │ │ ├── stats.dart │ │ ├── subtitle.dart │ │ └── ui.dart │ ├── settings.dart │ └── watch.dart │ └── theme │ ├── amethyst.dart │ ├── coldPurple.dart │ ├── hotPink.dart │ ├── lime.dart │ ├── mocha.dart │ ├── monochrome.dart │ ├── neonGreen.dart │ ├── sakura.dart │ ├── themes.dart │ └── types.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 ├── 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 ├── pubspec.lock ├── pubspec.yaml ├── test └── widget_test.dart ├── web ├── favicon.png ├── icons │ ├── Icon-192.png │ ├── Icon-512.png │ ├── Icon-maskable-192.png │ └── Icon-maskable-512.png ├── index.html ├── manifest.json └── splash │ └── img │ ├── dark-1x.png │ ├── dark-2x.png │ ├── dark-3x.png │ ├── dark-4x.png │ ├── light-1x.png │ ├── light-2x.png │ ├── light-3x.png │ └── light-4x.png └── 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 /.env_example: -------------------------------------------------------------------------------- 1 | SIMKL_CLIENT_ID="YOUR CLIENT ID" 2 | SIMKL_CLIENT_SECRET="YOUR CLIENT SECRET" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | **/ios/Flutter/.last_build_id 27 | .dart_tool/ 28 | .flutter-plugins 29 | .flutter-plugins-dependencies 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Symbolication related 35 | app.*.symbols 36 | 37 | # Obfuscation related 38 | app.*.map.json 39 | 40 | # Android Studio will place build artifacts here 41 | /android/app/debug 42 | /android/app/profile 43 | /android/app/release 44 | 45 | flutter_*.png 46 | 47 | *.env 48 | *.env.g.dart 49 | 50 | todo.md -------------------------------------------------------------------------------- /.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: "db7ef5bf9f59442b0e200a90587e8fa5e0c6336a" 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: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a 17 | base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a 18 | - platform: android 19 | create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a 20 | base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a 21 | - platform: ios 22 | create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a 23 | base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a 24 | - platform: linux 25 | create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a 26 | base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a 27 | - platform: macos 28 | create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a 29 | base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a 30 | - platform: web 31 | create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a 32 | base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a 33 | - platform: windows 34 | create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a 35 | base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a 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/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "java.configuration.updateBuildConfiguration": "interactive", 3 | "cmake.ignoreCMakeListsMissing": true 4 | } -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | 11 | linter: 12 | # The lint rules applied to this project can be customized in the 13 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 14 | # included above or to enable additional rules. A list of all available lints 15 | # and their documentation is published at https://dart.dev/lints. 16 | # 17 | # Instead of disabling a lint rule for the entire project in the 18 | # section below, it can also be suppressed for a single line of code 19 | # or a specific dart file by using the `// ignore: name_of_lint` and 20 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 21 | # producing the lint. 22 | rules: 23 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 24 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 25 | 26 | # Additional information about this file can be found at 27 | # https://dart.dev/guides/language/analysis-options 28 | -------------------------------------------------------------------------------- /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 | 15 | #cxx folder 16 | **/.cxx 17 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | id "dev.flutter.flutter-gradle-plugin" 5 | } 6 | 7 | def localProperties = new Properties() 8 | def localPropertiesFile = rootProject.file('local.properties') 9 | if (localPropertiesFile.exists()) { 10 | localPropertiesFile.withReader('UTF-8') { reader -> 11 | localProperties.load(reader) 12 | } 13 | } 14 | 15 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 16 | if (flutterVersionCode == null) { 17 | flutterVersionCode = '1' 18 | } 19 | 20 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 21 | if (flutterVersionName == null) { 22 | flutterVersionName = '1.0' 23 | } 24 | 25 | def keystoreProperties = new Properties() 26 | 27 | def keystorePropertiesFile = rootProject.file('key.properties') 28 | if(keystorePropertiesFile.exists()) { 29 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) 30 | } 31 | 32 | android { 33 | namespace "app.animestream" 34 | compileSdkVersion 35 35 | ndkVersion flutter.ndkVersion 36 | 37 | compileOptions { 38 | sourceCompatibility JavaVersion.VERSION_17 39 | targetCompatibility JavaVersion.VERSION_17 40 | } 41 | 42 | kotlinOptions { 43 | jvmTarget = JavaVersion.VERSION_17 44 | } 45 | 46 | sourceSets { 47 | main.java.srcDirs += 'src/main/kotlin' 48 | } 49 | 50 | defaultConfig { 51 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 52 | applicationId "app.animestream" 53 | // You can update the following values to match your application needs. 54 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. 55 | minSdkVersion 24 56 | targetSdkVersion 34 57 | versionCode flutterVersionCode.toInteger() 58 | versionName flutterVersionName 59 | } 60 | 61 | signingConfigs { 62 | release { 63 | keyAlias keystoreProperties['keyAlias'] 64 | keyPassword keystoreProperties['keyPassword'] 65 | storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null 66 | storePassword keystoreProperties['storePassword'] 67 | } 68 | } 69 | 70 | buildTypes { 71 | release { 72 | // TODO: Add your own signing config for the release build. 73 | // Signing with the debug keys for now, so `flutter run --release` works. 74 | signingConfig signingConfigs.release 75 | } 76 | 77 | debug { 78 | applicationIdSuffix ".debug" 79 | } 80 | } 81 | } 82 | 83 | flutter { 84 | source '../..' 85 | } 86 | 87 | dependencies { 88 | implementation 'androidx.multidex:multidex:2.0.1' 89 | } 90 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 26 | 30 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 44 | 45 | 46 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 61 | 64 | 65 | -------------------------------------------------------------------------------- /android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java: -------------------------------------------------------------------------------- 1 | // Generated file. 2 | // 3 | // If you wish to remove Flutter's multidex support, delete this entire file. 4 | // 5 | // Modifications to this file should be done in a copy under a different name 6 | // as this file may be regenerated. 7 | 8 | package io.flutter.app; 9 | 10 | import android.app.Application; 11 | import android.content.Context; 12 | import androidx.annotation.CallSuper; 13 | import androidx.multidex.MultiDex; 14 | 15 | /** 16 | * Extension of {@link android.app.Application}, adding multidex support. 17 | */ 18 | public class FlutterMultiDexApplication extends Application { 19 | @Override 20 | @CallSuper 21 | protected void attachBaseContext(Context base) { 22 | super.attachBaseContext(base); 23 | MultiDex.install(this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/app/animestream/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package app.animestream 2 | 3 | import android.widget.Toast 4 | import android.os.Looper 5 | import android.os.Handler 6 | import androidx.annotation.NonNull 7 | 8 | import io.flutter.embedding.android.FlutterActivity 9 | import io.flutter.embedding.engine.FlutterEngine 10 | import io.flutter.plugin.common.MethodChannel 11 | 12 | 13 | class MainActivity: FlutterActivity() { 14 | 15 | override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { 16 | super.configureFlutterEngine(flutterEngine) 17 | MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "animestream.app/utils").setMethodCallHandler { 18 | call, result -> 19 | if(call.method == "showToast") { 20 | val message = call.argument("message") 21 | if(message == null || message.length == 0) { 22 | result.error("MESSAGE_NOT_PROVIDED", "MESSAGE IS NULL OR EMPTY", null) 23 | } 24 | showToast(message ?: "") 25 | } else { 26 | result.notImplemented() 27 | } 28 | } 29 | } 30 | 31 | fun showToast(message: String) { 32 | Handler(Looper.getMainLooper()).post { 33 | Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-hdpi/android12splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-hdpi/android12splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-hdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-hdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-hdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-hdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-mdpi/android12splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-mdpi/android12splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-mdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-mdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-mdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-mdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night-hdpi/android12splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-night-hdpi/android12splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night-hdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-night-hdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night-mdpi/android12splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-night-mdpi/android12splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night-mdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-night-mdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night-v21/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-night-v21/background.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night-xhdpi/android12splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-night-xhdpi/android12splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night-xhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-night-xhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night-xxhdpi/android12splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night-xxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-night-xxhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night-xxxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-night-xxxhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-night/background.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-v21/background.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xhdpi/android12splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-xhdpi/android12splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-xhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-xhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxhdpi/android12splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-xxhdpi/android12splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-xxhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-xxhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxxhdpi/android12splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-xxxhdpi/android12splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxxhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable-xxxhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable/background.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/drawable/banner.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values-night-v31/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 18 | 21 | 22 | -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 19 | 22 | 23 | -------------------------------------------------------------------------------- /android/app/src/main/res/values-v31/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 18 | 21 | 22 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #1a1718 4 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 19 | 22 | 23 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /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 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-8.5-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 | settings.ext.flutterSdkPath = flutterSdkPath() 10 | 11 | includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") 12 | 13 | repositories { 14 | google() 15 | mavenCentral() 16 | gradlePluginPortal() 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false 21 | } 22 | } 23 | 24 | plugins { 25 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 26 | id "com.android.application" version "8.3.0" apply false 27 | id "org.jetbrains.kotlin.android" version "1.9.0" apply false 28 | } 29 | 30 | include ":app" 31 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 1.3.6 -> 1.3.7 2 | 3 | **Ah yes, Yet another patch n fix update!** 4 | 5 | ## New Features & Changes 6 | 7 | - Few more controls towards subtitles 8 | - New theme! (atp thats all im capable of. I hope its the final theme) 9 | - Few modifications for list page in Windows 10 | - Sub/Dub toggle! (availability will depend on luck & server!) 11 | - Added a quick access to subtitles page on holding subtitle button from watch page. 12 | - No new sources (hehe! will add one next time if the stars align) 13 | - Minor UI tweaks 14 | 15 | ## Fixes 16 | 17 | - Fixed **ASS** subtitle parsing. (Fixes flawed subs in AnimeOnsen) 18 | - Fixed AniPlay (please dont break now :pray:) 19 | - Fixed Gojo 20 | - To Fix animepahe, use a VPN! 21 | - Fixed subtitles not being updated when navigated to new episode 22 | - Fixed more white screen issues. (I really hope this is the last one.) 23 | - Fixed some UI inconsistancies 24 | 25 | ## Issues 26 | 27 | - Windows version is lacking sub/dub toggle. It will be there in next patch, im redoing the info page UI on windows. 28 | - The apk size bulked by ~1 MB due to added fonts for subtitle customisation. (Is this even an issue?) 29 | 30 | **Yep! That's it.** 31 | 32 | I fr forgot to track the changes, so there are changes in the app which arent mentioned above! 33 | Plugins has to wait :) 34 | 35 | Spent an awful lot of time on plugins. And yes, it didnt work out like I expected. It did work, 36 | just not according to my style and expectations! So, this is a small bug sqash update! 37 | 38 | If you are still encountering the white/gray screen issue or any other issues, submit it on github issues, discord or reddit. 39 | 40 | As always, love y'all and Until Next Version,
41 | **Cya!** 42 | -------------------------------------------------------------------------------- /devtools_options.yaml: -------------------------------------------------------------------------------- 1 | extensions: 2 | - provider: true -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 11.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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 | }, 7 | { 8 | "appearances" : [ 9 | { 10 | "appearance" : "luminosity", 11 | "value" : "dark" 12 | } 13 | ], 14 | "filename" : "darkbackground.png", 15 | "idiom" : "universal" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.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 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "filename" : "LaunchImageDark.png", 16 | "idiom" : "universal", 17 | "scale" : "1x" 18 | }, 19 | { 20 | "filename" : "LaunchImage@2x.png", 21 | "idiom" : "universal", 22 | "scale" : "2x" 23 | }, 24 | { 25 | "appearances" : [ 26 | { 27 | "appearance" : "luminosity", 28 | "value" : "dark" 29 | } 30 | ], 31 | "filename" : "LaunchImageDark@2x.png", 32 | "idiom" : "universal", 33 | "scale" : "2x" 34 | }, 35 | { 36 | "filename" : "LaunchImage@3x.png", 37 | "idiom" : "universal", 38 | "scale" : "3x" 39 | }, 40 | { 41 | "appearances" : [ 42 | { 43 | "appearance" : "luminosity", 44 | "value" : "dark" 45 | } 46 | ], 47 | "filename" : "LaunchImageDark@3x.png", 48 | "idiom" : "universal", 49 | "scale" : "3x" 50 | } 51 | ], 52 | "info" : { 53 | "author" : "xcode", 54 | "version" : 1 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@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 | 45 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Animestream 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | animestream 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | CADisableMinimumFrameDurationOnPhone 45 | 46 | UIApplicationSupportsIndirectInputEvents 47 | 48 | UIStatusBarHidden 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /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/assets/fonts/ARIAL.TTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/fonts/ARIAL.TTF -------------------------------------------------------------------------------- /lib/assets/fonts/ARIALBD.TTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/fonts/ARIALBD.TTF -------------------------------------------------------------------------------- /lib/assets/fonts/Helvetica-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/fonts/Helvetica-Bold.ttf -------------------------------------------------------------------------------- /lib/assets/fonts/Helvetica.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/fonts/Helvetica.ttf -------------------------------------------------------------------------------- /lib/assets/fonts/NotoSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/fonts/NotoSans-Bold.ttf -------------------------------------------------------------------------------- /lib/assets/fonts/NotoSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/fonts/NotoSans-Regular.ttf -------------------------------------------------------------------------------- /lib/assets/fonts/NunitoSans_10pt-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/fonts/NunitoSans_10pt-Bold.ttf -------------------------------------------------------------------------------- /lib/assets/fonts/NunitoSans_10pt-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/fonts/NunitoSans_10pt-Medium.ttf -------------------------------------------------------------------------------- /lib/assets/fonts/Poppins-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/fonts/Poppins-Bold.ttf -------------------------------------------------------------------------------- /lib/assets/fonts/Rubik-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/fonts/Rubik-Bold.ttf -------------------------------------------------------------------------------- /lib/assets/fonts/Rubik-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/fonts/Rubik-Medium.ttf -------------------------------------------------------------------------------- /lib/assets/icons/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/icons/logo.png -------------------------------------------------------------------------------- /lib/assets/icons/logo_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/icons/logo_background.png -------------------------------------------------------------------------------- /lib/assets/icons/logo_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/icons/logo_foreground.png -------------------------------------------------------------------------------- /lib/assets/icons/logo_foreground_splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/icons/logo_foreground_splash.png -------------------------------------------------------------------------------- /lib/assets/icons/logo_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/icons/logo_monochrome.png -------------------------------------------------------------------------------- /lib/assets/images/broken_heart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/images/broken_heart.png -------------------------------------------------------------------------------- /lib/assets/images/check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/images/check.png -------------------------------------------------------------------------------- /lib/assets/images/chisato.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/images/chisato.jpeg -------------------------------------------------------------------------------- /lib/assets/images/chisato_AI.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/images/chisato_AI.jpg -------------------------------------------------------------------------------- /lib/assets/images/ghost.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/images/ghost.png -------------------------------------------------------------------------------- /lib/assets/images/mitsuha.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/images/mitsuha.jpg -------------------------------------------------------------------------------- /lib/assets/images/profile_banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/images/profile_banner.jpg -------------------------------------------------------------------------------- /lib/assets/images/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/lib/assets/images/search.png -------------------------------------------------------------------------------- /lib/core/anime/downloader/types.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | class DownloadingItem { 4 | final int id; 5 | bool downloading; 6 | final String? streamLink; 7 | final String? fileName; 8 | final int retryAttempts; 9 | final int parallelBatches; 10 | 11 | DownloadingItem({ 12 | required this.id, 13 | required this.downloading, 14 | this.streamLink, 15 | this.fileName, 16 | this.retryAttempts = 5, 17 | this.parallelBatches = 5, 18 | }); 19 | } 20 | 21 | class BufferItem { 22 | final int index; 23 | final Uint8List buffer; 24 | 25 | BufferItem({required this.index, required this.buffer}); 26 | } 27 | -------------------------------------------------------------------------------- /lib/core/anime/extractors/kwik.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/anime/extractors/type.dart'; 2 | import 'package:animestream/core/anime/providers/types.dart'; 3 | import 'package:http/http.dart'; 4 | import 'package:html/parser.dart' as html; 5 | 6 | class Kwik extends AnimeExtractor { 7 | Future> extract(String streamUrl, {String? quality, String? server}) async { 8 | final res = await get(Uri.parse(streamUrl), headers: {'referer': 'https://animepahe.ru/'}); 9 | final doc = html.parse(res.body); 10 | String? streamLink; 11 | doc.querySelectorAll("script").forEach((element) { 12 | final html = element.innerHtml; 13 | final regex = RegExp(r'eval\(function\(p,a,c,k,e,d\)'); 14 | final match = regex.firstMatch(html); 15 | if (match != null) { 16 | final unpacked = JsUnpack(html).unpack(); 17 | final dataMatch = RegExp(r"const\s+source\s*=\s*'([^']+\.m3u8)'").allMatches(unpacked).firstOrNull?[1] ?? ''; 18 | streamLink = dataMatch.replaceAll(RegExp(r'{|}|\"|file:'), ''); 19 | } 20 | }); 21 | 22 | if (streamLink == null) throw new Exception("UNABLE TO EXTRACT KWIK STREAM"); 23 | 24 | return [VideoStream(quality: quality ?? "single", link: streamLink!, isM3u8: streamLink!.endsWith("m3u8"), server: server ?? "Kwik", backup: false)]; 25 | } 26 | } 27 | 28 | class JsUnpack { 29 | final String source; 30 | const JsUnpack(this.source); 31 | static const alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 32 | 33 | ///Unpacks P.A.C.K.E.R. packed js code 34 | String unpack() { 35 | final lst = _filterargs(); 36 | final String payload = lst[0].replaceAll("\\\\", "\\").replaceAll("\\'", "'"); 37 | final List symtab = lst[1]; 38 | String source = payload; 39 | final reg = RegExp( 40 | r"\b\w+\b", 41 | ).allMatches(payload); 42 | int correct = 0; 43 | for (RegExpMatch element in reg) { 44 | final word = payload.substring(element.start, element.end); 45 | String lookUp = ""; 46 | final v = toBase10(word); 47 | if (v < symtab.length) { 48 | try { 49 | lookUp = symtab[v]; 50 | } catch (_) {} 51 | if (lookUp.isEmpty) lookUp = word; 52 | } else { 53 | lookUp = word; 54 | } 55 | source = source.replaceRange(element.start + correct, element.start + word.length + correct, lookUp); 56 | correct += lookUp.length - (element.end - element.start); 57 | } 58 | return _replaceStrings(source); 59 | } 60 | 61 | String _replaceStrings(String source) { 62 | var re = RegExp(r'var *(_\w+)=\["(.*?)"];', dotAll: true).firstMatch(source); 63 | if (re == null) { 64 | return source; 65 | } 66 | final strings = re.group(1)!; 67 | return source.substring(strings.length); 68 | } 69 | 70 | List _filterargs() { 71 | final all = RegExp(r"}\s*\('(.*)',\s*(.*?),\s*(\d+),\s*'(.*?)'\.split\('\|'\)").firstMatch(source); 72 | if (all == null) { 73 | throw 'Corrupted p.a.c.k.e.r. data.'; 74 | } 75 | return [all.group(1), all.group(4)!.split("|"), int.tryParse(all.group(2)!) ?? 36, int.parse(all.group(3)!)]; 76 | } 77 | 78 | int toBase10(String string) { 79 | return string.split('').fold(0, (int out, char) { 80 | int charIndex = alphabet.indexOf(char); 81 | return out * alphabet.length + charIndex; 82 | }); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /lib/core/anime/extractors/type.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/anime/providers/types.dart'; 2 | 3 | abstract class AnimeExtractor { 4 | Future> extract(String streamUrl); 5 | } 6 | -------------------------------------------------------------------------------- /lib/core/anime/providers/animeProvider.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/anime/providers/types.dart'; 2 | 3 | abstract class AnimeProvider { 4 | /**Name of the provider */ 5 | String get providerName; 6 | 7 | //should provide search results with keys: name, image, alias 8 | Future>> search(String query); 9 | 10 | /** 11 | * Should return a list of string that is the link to get to that episode 12 | */ 13 | Future>> getAnimeEpisodeLink(String aliasId, { bool dub = false }); 14 | 15 | /** 16 | * The link format returned in the [getAnimeEpisodeLink] method should be 17 | * parsed in this method 18 | */ 19 | Future getStreams(String episodeId, Function(List, bool) update, { bool dub = false, String? metadata }); 20 | 21 | /** 22 | * The link format returned in the [getAnimeEpisodeLink] method should be 23 | * parsed in this method 24 | * 25 | * This method should return a list of [VideoStream] objects through callbacks containing direct download 26 | * links to the episode 27 | */ 28 | Future getDownloadSources(String episodeUrl, Function(List, bool) update, {bool dub = false, String? metadata}); 29 | } 30 | -------------------------------------------------------------------------------- /lib/core/anime/providers/providerDetails.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: public_member_api_docs, sort_constructors_first 2 | import 'dart:convert'; 3 | 4 | class ProviderDetails { 5 | final String name; 6 | final String identifier; 7 | final String version; 8 | final String? icon; 9 | final String? code; 10 | final bool supportDownloads; 11 | 12 | ProviderDetails({ 13 | required this.name, 14 | required this.identifier, 15 | required this.version, 16 | this.icon, 17 | this.code, 18 | this.supportDownloads = false, 19 | }); 20 | 21 | ProviderDetails copyWith({ 22 | String? name, 23 | String? identifier, 24 | String? version, 25 | String? icon, 26 | String? code, 27 | bool? supportDownloads, 28 | }) { 29 | return ProviderDetails( 30 | name: name ?? this.name, 31 | identifier: identifier ?? this.identifier, 32 | version: version ?? this.version, 33 | icon: icon ?? this.icon, 34 | code: code ?? this.code, 35 | supportDownloads: supportDownloads ?? this.supportDownloads, 36 | ); 37 | } 38 | 39 | Map toMap() { 40 | return { 41 | 'name': name, 42 | 'identifier': identifier, 43 | 'version': version, 44 | 'icon': icon, 45 | 'code': code, 46 | 'supportDownloads': supportDownloads, 47 | }; 48 | } 49 | 50 | factory ProviderDetails.fromMap(Map map) { 51 | return ProviderDetails( 52 | name: map['name'] as String, 53 | identifier: map['identifier'] as String, 54 | version: map['version'] as String, 55 | icon: map['icon'] != null ? map['icon'] as String : null, 56 | code: map['code'] != null ? map['code'] as String : null, 57 | supportDownloads: map['supportDownloads'] as bool, 58 | ); 59 | } 60 | 61 | String toJson() => json.encode(toMap()); 62 | 63 | factory ProviderDetails.fromJson(String source) => ProviderDetails.fromMap(json.decode(source) as Map); 64 | 65 | @override 66 | String toString() { 67 | return 'ProviderDetails(name: $name, identifier: $identifier, version: $version, icon: $icon, code: $code, supportDownloads: $supportDownloads)'; 68 | } 69 | 70 | @override 71 | int get hashCode { 72 | return name.hashCode ^ 73 | identifier.hashCode ^ 74 | version.hashCode ^ 75 | icon.hashCode ^ 76 | code.hashCode ^ 77 | supportDownloads.hashCode; 78 | } 79 | 80 | @override 81 | bool operator ==(covariant ProviderDetails other) { 82 | if (identical(this, other)) return true; 83 | 84 | return 85 | other.name == name && 86 | other.identifier == identifier && 87 | other.version == version && 88 | other.icon == icon && 89 | other.code == code && 90 | other.supportDownloads == supportDownloads; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /lib/core/anime/providers/providerManager.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:animestream/core/anime/providers/providerDetails.dart'; 4 | import 'package:animestream/core/data/providers.dart'; 5 | import 'package:http/http.dart'; 6 | 7 | class ProviderManager { 8 | static const String _fileBaseUrl = "https://raw.githubusercontent.com/frostnova721/provins/master/lib/providers/"; 9 | 10 | static const String _indexUrl = "https://raw.githubusercontent.com/frostnova721/provins/master/index.json"; 11 | 12 | final _providersPreferences = ProvidersPreferences(); 13 | 14 | /// Get the saved(Installed) provider's code. 15 | Future getSavedProviderCode(String providerIdentifier) async { 16 | return (await _providersPreferences.getProvider(providerIdentifier))?.code; 17 | } 18 | 19 | /// Get the list of all saved providers. 20 | Future> getSavedProviders() async { 21 | return await _providersPreferences.listAllProviders(); 22 | } 23 | 24 | /// Save/Install a provider. 25 | Future saveProvider(ProviderDetails provider) async { 26 | return await _providersPreferences.saveProvider(provider); 27 | } 28 | 29 | /// Remove/Uninstall a provider. 30 | Future removeProvider(ProviderDetails provider) async { 31 | return await _providersPreferences.removeProvider(provider.identifier); 32 | } 33 | 34 | /// Fetch the code for the provider from the repo. 35 | Future fetchProviderCode(String providerIdentifier) async { 36 | final url = _fileBaseUrl + "$providerIdentifier/$providerIdentifier.dart"; 37 | final res = await get(Uri.parse(url)); 38 | return res.statusCode == 200 ? res.body : null; 39 | } 40 | 41 | /// Yeah, fetch the repo. 42 | Future> fetchProvidersRepo() async { 43 | final availableProviders = await get(Uri.parse(_indexUrl)); 44 | final List jsoned = jsonDecode(availableProviders.body) as List; 45 | final List> mapped = jsoned.map((e) => Map.from(e as Map).cast()).toList(); 46 | final classed = mapped.map((e) => ProviderDetails.fromMap(e)).toList(); 47 | return classed; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/core/anime/providers/providerPlugin.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/anime/providers/animeProvider.dart'; 2 | import 'package:animestream/core/anime/providers/providerManager.dart'; 3 | // import 'package:d4rt/d4rt.dart'; 4 | 5 | class ProviderPlugin { 6 | 7 | ProviderPlugin() { 8 | _setupCompiler(); 9 | } 10 | 11 | final Map _compiledProviders = {}; 12 | 13 | void _setupCompiler() {} 14 | 15 | Future getProvider(String provider, {String? testCode}) async { 16 | if (provider.isEmpty && testCode == null) return null; 17 | 18 | final cachedProvider = _compiledProviders[provider]; 19 | if (cachedProvider != null) return cachedProvider; 20 | 21 | print("Cache miss. compiling provider."); 22 | 23 | final program = testCode != null ? testCode : await ProviderManager().getSavedProviderCode(provider); 24 | 25 | if (program == null) return null; 26 | 27 | // final d4rt = D4rt(); 28 | 29 | // d4rt.registerBridgedClass(AnimeProviderBridge.$bridger); 30 | // d4rt.registerBridgedClass(AnimeProviderBridge.videoStreamBridge); 31 | // HttpRegisters.register(d4rt); 32 | // HtmlRegister().register(d4rt); 33 | 34 | // await d4rt.execute(rc()); 35 | 36 | // return APWrapper(d4rt); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/core/anime/providers/registers/http.dart: -------------------------------------------------------------------------------- 1 | // import 'package:d4rt/d4rt.dart'; 2 | // import 'package:http/http.dart'; 3 | 4 | // class HttpRegisters { 5 | // static void register(D4rt d4rt) { 6 | // // Register GET 7 | // d4rt.registertopLevelFunction("get", 8 | // (InterpreterVisitor? v, List args, Map namedArgs, List? rt) { 9 | // final Map headers = (namedArgs['headers'] as Map).map( 10 | // (key, value) => MapEntry(key.toString(), value.toString()), 11 | // ); 12 | // return get(args[0] as Uri, headers: headers); 13 | // }); 14 | 15 | // // Register POST 16 | // d4rt.registertopLevelFunction("post", 17 | // (InterpreterVisitor? v, List args, Map namedArgs, List? rt) { 18 | // final Map headers = (namedArgs['headers'] as Map).map( 19 | // (key, value) => MapEntry(key.toString(), value.toString()), 20 | // ); 21 | // return post(args[0] as Uri, headers: headers, body: namedArgs['body']); 22 | // }); 23 | 24 | // // Register Response class 25 | // d4rt.registerBridgedClass(BridgedClassDefinition( 26 | // nativeType: Response, 27 | // name: 'Response', 28 | // constructors: { 29 | // '': (visitor, positionalArgs, namedArgs) { 30 | // return Response; 31 | // }, 32 | // }, 33 | // getters: { 34 | // 'statusCode': (visitor, target) => (target as Response).statusCode, 35 | // 'body': (visitor, target) => (target as Response).body, 36 | // 'headers': (visitor, target) => (target as Response).headers, 37 | // 'isRedirect': (visitor, target) => (target as Response).isRedirect, 38 | // 'reasonPhrase': (visitor, target) => (target as Response).reasonPhrase, 39 | // 'contentLength': (visitor, target) => (target as Response).contentLength, 40 | // 'bodyBytes': (visitor, target) => (target as Response).bodyBytes, 41 | // 'persistentConnection': (visitor, target) => (target as Response).persistentConnection, 42 | // 'request': (visitor, target) => (target as Response).request, 43 | // }, 44 | // )); 45 | // } 46 | // } 47 | -------------------------------------------------------------------------------- /lib/core/app/logging.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | class Logger { 4 | static final Logger _instance = Logger._internal(); 5 | Logger._internal(); 6 | factory Logger() => _instance; 7 | 8 | final List _logBuffer = []; 9 | 10 | void addLog(String log) { 11 | _logBuffer.add(log); 12 | } 13 | 14 | void clearLog() => _logBuffer.clear(); 15 | 16 | Future writeLog() async { 17 | //write the log to Documents folder 18 | final dir = await Directory('/storage/emulated/0/Documents/animestream/logs'); 19 | if(!(await dir.exists())) { 20 | await dir.create(recursive: true); 21 | } 22 | final now = DateTime.now(); 23 | final dateAndTime = "${now.day}${now.month}${now.year}_${now.hour}${now.minute}${now.second}"; 24 | final filePath = "${dir.path}/$dateAndTime.txt"; 25 | final file = File(filePath); 26 | final data = _logBuffer.join(' \n'); 27 | await file.writeAsString(data); 28 | print("written stuff to $filePath"); 29 | } 30 | } -------------------------------------------------------------------------------- /lib/core/app/runtimeDatas.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/data/types.dart'; 2 | import 'package:animestream/core/database/anilist/types.dart'; 3 | import 'package:animestream/ui/theme/types.dart'; 4 | import 'package:flutter_dotenv/flutter_dotenv.dart'; 5 | 6 | //saved anilist data 7 | UserModal? storedUserData; 8 | 9 | //saved settings 10 | SettingsModal? currentUserSettings; 11 | 12 | //saved theme 13 | late AnimeStreamTheme appTheme; 14 | 15 | //active theme's themeItem 16 | late ThemeItem activeThemeItem; 17 | 18 | late String animeOnsenToken; 19 | 20 | String simklClientId = dotenv.get("SIMKL_CLIENT_ID"); -------------------------------------------------------------------------------- /lib/core/commons/enums.dart: -------------------------------------------------------------------------------- 1 | enum SettingKey { megaSkipDuration, skipDuration } 2 | 3 | enum RequestType { recentlyUpdatedAnime, media, mutate } 4 | 5 | enum ServerSheetType { watch, download } 6 | 7 | enum MediaStatus { CURRENT, PLANNING, COMPLETED, DROPPED, PAUSED } 8 | 9 | enum SortType { AtoZ, RecentlyUpdated, TopRated } 10 | 11 | enum EpisodeViewModes { tile, grid, list } 12 | 13 | enum SubtitleFormat { 14 | ASS, 15 | VTT; 16 | 17 | static SubtitleFormat fromName(String name) { 18 | return switch (name.toLowerCase()) { 19 | "vtt" => SubtitleFormat.VTT, 20 | "ass" => SubtitleFormat.ASS, 21 | _ => throw ArgumentError("$name doesnt exist on SubtitleFormat enum"), 22 | }; 23 | } 24 | } 25 | 26 | enum HiveKey { 27 | manualSearches, 28 | userPreferences, 29 | settings, 30 | theme, 31 | watching, 32 | lastWatchDuration, 33 | 34 | @deprecated 35 | token, 36 | } 37 | 38 | enum SecureStorageKey { 39 | //tokens 40 | simklToken("simkl_token"), 41 | anilistToken("anilist_token"), 42 | malToken("mal_token"), 43 | 44 | //auth objects 45 | malAuthResponse("mal_auth_response"), 46 | 47 | //codes 48 | malChallengeVerifier("mal_challenge_verifier"); 49 | 50 | final String value; 51 | 52 | const SecureStorageKey(this.value); 53 | } 54 | 55 | enum PlayerState { 56 | playing, 57 | paused, 58 | buffering, 59 | } 60 | -------------------------------------------------------------------------------- /lib/core/commons/extractQuality.dart: -------------------------------------------------------------------------------- 1 | import 'package:http/http.dart'; 2 | 3 | String _makeBaseLink(String uri) { 4 | final split = uri.split('/'); 5 | split.removeLast(); 6 | return split.join('/'); 7 | } 8 | 9 | Future>> getQualityStreams(String streamUrl, { Map? customHeader = null}) async { 10 | try { 11 | final content = (await get(Uri.parse(streamUrl), headers: customHeader)).body; 12 | // print(content); 13 | 14 | List links = []; 15 | List resolutions = []; 16 | 17 | List lines = content.split("\n"); 18 | // lines = lines.where((it) => !it.startsWith("EXT-X-MEDIA")).toList().first.split("\n"); 19 | 20 | final regex = RegExp(r'RESOLUTION=(\d+x\d+)'); 21 | for (final line in lines) { 22 | if (line.startsWith("#")) { 23 | if (line.startsWith('#EXTM3U') || line.startsWith('#EXT-X-I-FRAME') || line.startsWith("#EXT-X-MEDIA")) 24 | continue; 25 | final match = regex.allMatches(line).first; 26 | resolutions.add(match.group(0)?.replaceAll("RESOLUTION=", '') ?? 'null'); 27 | } else { 28 | print(line); 29 | final linkPart = line.trim(); 30 | if (linkPart.length > 1) 31 | links.add(linkPart.startsWith('http') 32 | ? linkPart 33 | : "${_makeBaseLink(streamUrl)}/$linkPart"); 34 | } 35 | } 36 | 37 | List> grouped = []; 38 | 39 | for (int i = 0; i < links.length; i++) { 40 | final Map obj = { 41 | 'link': links[i], 42 | 'resolution': resolutions[i], 43 | 'quality': resolutions[i].split('x')[1] + "p", 44 | }; 45 | grouped.add(obj); 46 | } 47 | 48 | return grouped; 49 | } catch(err) { 50 | return [{ 51 | 'link' : streamUrl, 52 | 'resolution': "", 53 | 'quality': 'default' 54 | }]; 55 | 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /lib/core/commons/types.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/anime/providers/types.dart'; 2 | import 'package:animestream/core/database/types.dart'; 3 | 4 | class ServerSelectionBottomSheetContentData { 5 | final int episodeIndex; 6 | final String title; 7 | final List epLinks; 8 | final String selectedSource; 9 | final int id; 10 | final String cover; 11 | final int? totalEpisodes; 12 | final double? lastWatchDuration; 13 | 14 | ServerSelectionBottomSheetContentData({ 15 | required this.episodeIndex, 16 | required this.epLinks, 17 | required this.selectedSource, 18 | required this.title, 19 | required this.id, 20 | required this.cover, 21 | required this.lastWatchDuration, 22 | this.totalEpisodes, 23 | }); 24 | } 25 | 26 | class WatchPageInfo { 27 | int episodeNumber; 28 | final String animeTitle; 29 | VideoStream streamInfo; 30 | int id; 31 | List altDatabases; 32 | double? lastWatchDuration; 33 | List allStreams; 34 | 35 | WatchPageInfo({ 36 | required this.id, 37 | required this.animeTitle, 38 | required this.episodeNumber, 39 | required this.streamInfo, 40 | required this.altDatabases, 41 | required this.lastWatchDuration, 42 | this.allStreams = const [], 43 | }); 44 | } 45 | 46 | class HomePageList { 47 | final String coverImage; 48 | final double? rating; 49 | final Map title; 50 | final int id; 51 | final int? totalEpisodes; 52 | final int? watchedEpisodeCount; 53 | 54 | HomePageList({ 55 | required this.coverImage, 56 | required this.rating, 57 | required this.title, 58 | required this.id, 59 | this.totalEpisodes, 60 | this.watchedEpisodeCount, 61 | }); 62 | } 63 | -------------------------------------------------------------------------------- /lib/core/commons/utils.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:animestream/core/commons/enums.dart'; 4 | import 'package:device_info_plus/device_info_plus.dart'; 5 | import 'package:http/http.dart'; 6 | 7 | Future fetch(String uri) async { 8 | final res = await get(Uri.parse(uri)); 9 | return res.body; 10 | } 11 | 12 | String getCurrentSeason() { 13 | final month = DateTime.now().month; 14 | switch (month) { 15 | case 1: 16 | case 2: 17 | case 3: 18 | return 'WINTER'; 19 | case 4: 20 | case 5: 21 | case 6: 22 | return 'SPRING'; 23 | case 7: 24 | case 8: 25 | case 9: 26 | return 'SUMMER'; 27 | case 10: 28 | case 11: 29 | case 12: 30 | return 'FALL'; 31 | default: 32 | return 'Unknown'; 33 | } 34 | } 35 | 36 | Map? MonthnumberToMonthName( 37 | int? monthNumber, 38 | ) { 39 | if (monthNumber == null) return {'short': '', 'full': ''}; 40 | if (monthNumber > 12 || monthNumber < 1) return null; 41 | const monthName = [ 42 | 'January', 43 | 'February', 44 | 'March', 45 | 'April', 46 | 'May', 47 | 'June', 48 | 'July', 49 | 'August', 50 | 'September', 51 | 'October', 52 | 'November', 53 | 'December', 54 | ]; 55 | return { 56 | 'full': monthName[monthNumber - 1], 57 | 'short': monthName[monthNumber - 1].substring(0, 3), 58 | }; 59 | } 60 | 61 | MediaStatus? assignItemEnum(String? valueInString) { 62 | if (valueInString == null) return null; 63 | switch (valueInString) { 64 | case "CURRENT": 65 | return MediaStatus.CURRENT; 66 | case "PLANNING": 67 | return MediaStatus.PLANNING; 68 | case "DROPPED": 69 | return MediaStatus.DROPPED; 70 | case "COMPLETED": 71 | return MediaStatus.COMPLETED; 72 | default: 73 | throw new Exception("ERR_BAD_STRING"); 74 | } 75 | } 76 | 77 | Future isTv() async { 78 | if(!Platform.isAndroid) return false; 79 | DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); 80 | AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; 81 | bool isTV = androidInfo.systemFeatures.contains('android.software.leanback'); 82 | return isTV; 83 | } 84 | -------------------------------------------------------------------------------- /lib/core/data/animeSpecificPreference.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/app/runtimeDatas.dart'; 2 | import 'package:animestream/core/commons/enums.dart'; 3 | import 'package:animestream/core/data/hive.dart'; 4 | import 'package:animestream/core/data/types.dart'; 5 | import 'package:animestream/core/database/database.dart'; 6 | import 'package:hive/hive.dart'; 7 | 8 | /// Retruns an object of [AnimeSpecificPreference] if it exists! 9 | Future getAnimeSpecificPreference(String anilistId) async { 10 | //just handle anilist 11 | if (currentUserSettings?.database != Databases.anilist) return null; 12 | 13 | var box = await Hive.openBox("animeInfo"); 14 | if (!box.isOpen) { 15 | box = await Hive.openBox("animeInfo"); 16 | } 17 | 18 | Map? lastWatchDuration; 19 | String? manualSearchString; 20 | 21 | final Map lastWatch = await box.get(HiveKey.lastWatchDuration.name) ?? {}; 22 | if (lastWatch.isEmpty) { 23 | print("EMPTY MAP 'lastWatchDuration'"); 24 | } 25 | 26 | lastWatchDuration = lastWatch[anilistId] ?? null; 27 | 28 | Map? manualSearchQuery = await box.get(HiveKey.manualSearches.name); 29 | if (manualSearchQuery?.isEmpty ?? true) { 30 | print("EMPTY MAP 'manualSearches'"); 31 | } 32 | 33 | manualSearchString = manualSearchQuery?[anilistId] ?? ''; 34 | if (manualSearchString?.isEmpty ?? true) { 35 | print("NO QUERY FOR ALTERNATE SEARCHING"); 36 | manualSearchString = null; 37 | } 38 | 39 | await box.close(); 40 | 41 | return AnimeSpecificPreference(lastWatchDuration: lastWatchDuration, manualSearchQuery: manualSearchString); 42 | } 43 | 44 | Future addLastWatchedDuration(String anilistId, Map item) async { 45 | Map map = await getVal(HiveKey.lastWatchDuration, boxName: "animeInfo") ?? {}; 46 | 47 | print(map); 48 | 49 | map[anilistId] = item; 50 | 51 | Map filteredMap = map; 52 | 53 | if (map.length > 40) { 54 | List> entries = map.entries.toList(); 55 | entries = entries.sublist(0, 40); 56 | filteredMap = Map.fromEntries(entries); 57 | } 58 | 59 | await storeVal(HiveKey.lastWatchDuration, filteredMap, boxName: "animeInfo"); 60 | } 61 | 62 | Future addManualSearchQuery(String anilistId, String searchTerm) async { 63 | Map map = await getVal(HiveKey.manualSearches, boxName: "animeInfo") ?? {}; 64 | map[anilistId] = searchTerm; 65 | Map filteredMap = map; 66 | 67 | if (map.length > 40) { 68 | List> entries = map.entries.toList(); 69 | entries = entries.sublist(0, 40); 70 | filteredMap = Map.fromEntries(entries); 71 | } 72 | 73 | await storeVal(HiveKey.manualSearches, filteredMap, boxName: "animeInfo"); 74 | } 75 | -------------------------------------------------------------------------------- /lib/core/data/hive.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/commons/enums.dart'; 2 | import 'package:hive/hive.dart'; 3 | 4 | Future? getVal(HiveKey itemKey, {String boxName = 'animestream'}) async { 5 | var box = await Hive.openBox(boxName); 6 | if (!box.isOpen) { 7 | box = await Hive.openBox(boxName); 8 | } 9 | final vals = await box.get(itemKey.name); 10 | await box.close(); 11 | return vals; 12 | } 13 | 14 | Future storeVal(HiveKey itemKey, dynamic val, {String boxName = 'animestream'}) async { 15 | try { 16 | var box = await Hive.openBox(boxName); 17 | if (!box.isOpen) { 18 | box = await Hive.openBox(boxName); 19 | } 20 | await box.put(itemKey.name, val); 21 | await box.close(); 22 | } catch (err) { 23 | print(err); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/core/data/misc.dart: -------------------------------------------------------------------------------- 1 | import 'package:hive_flutter/hive_flutter.dart'; 2 | 3 | /// Used for storage of keys from providers. nothing else 4 | 5 | Future getMiscVal(String key) async { 6 | final box = await Hive.openBox("misc"); 7 | final stuff = await box.get(key); 8 | await box.close(); 9 | return stuff; 10 | } 11 | 12 | Future storeMiscVal(String key, dynamic value) async { 13 | final box = await Hive.openBox("misc"); 14 | await box.put(key, value); 15 | await box.close(); 16 | return; 17 | } 18 | -------------------------------------------------------------------------------- /lib/core/data/preferences.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/commons/enums.dart'; 2 | import 'package:animestream/core/data/hive.dart'; 3 | import 'package:animestream/core/data/types.dart'; 4 | 5 | class UserPreferences { 6 | static Future getUserPreferences() async { 7 | Map? prefMap = await getVal(HiveKey.userPreferences); 8 | if(prefMap == null || prefMap.isEmpty) prefMap = UserPreferencesModal().toMap(); 9 | return UserPreferencesModal.fromMap(prefMap); 10 | } 11 | 12 | static Future saveUserPreferences(UserPreferencesModal userPreferences) async { 13 | final mapped = userPreferences.toMap(); 14 | await storeVal(HiveKey.userPreferences, mapped); 15 | } 16 | } -------------------------------------------------------------------------------- /lib/core/data/providers.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/anime/providers/providerDetails.dart'; 2 | import 'package:hive/hive.dart'; 3 | 4 | class ProvidersPreferences { 5 | final _boxKey = "anime_providers"; 6 | 7 | Future getProvider(String identifier) async { 8 | final box = await Hive.openBox(_boxKey); 9 | final Map? provider = (await box.get(identifier) as Map).cast(); 10 | await box.close(); 11 | return ProviderDetails?.fromMap(provider!); 12 | } 13 | 14 | Future> listAllProviders() async { 15 | final box = await Hive.openBox(_boxKey); 16 | final List providers = await box.values.toList(); 17 | final List> mappedList = providers.map((it) => Map.from(it as Map).cast()).toList(); 18 | await box.close(); 19 | return mappedList.map((e) => ProviderDetails.fromMap(e)).toList(); 20 | } 21 | 22 | Future saveProvider(ProviderDetails provider) async { 23 | final box = await Hive.openBox(_boxKey); 24 | await box.put(provider.identifier, provider.toMap()); 25 | await box.close(); 26 | } 27 | 28 | Future removeProvider(String identifier) async { 29 | final box = await Hive.openBox(_boxKey); 30 | await box.delete(identifier); 31 | await box.close(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/core/data/secureStorage.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/commons/enums.dart'; 2 | import 'package:flutter_secure_storage/flutter_secure_storage.dart'; 3 | 4 | Future getSecureVal(SecureStorageKey key) async { 5 | final st = FlutterSecureStorage(aOptions: AndroidOptions(encryptedSharedPreferences: true)); 6 | final item = await st.read(key: key.value); 7 | return item; 8 | } 9 | 10 | Future storeSecureVal(SecureStorageKey key, String? val) async { 11 | final st = FlutterSecureStorage(aOptions: AndroidOptions(encryptedSharedPreferences: true)); 12 | await st.write(key: key.value, value: val); 13 | } -------------------------------------------------------------------------------- /lib/core/data/settings.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/app/runtimeDatas.dart'; 2 | import 'package:animestream/core/commons/enums.dart'; 3 | import 'package:animestream/core/data/types.dart'; 4 | import 'package:hive/hive.dart'; 5 | 6 | class Settings { 7 | Future getSettings({bool writing = false}) async { 8 | var box = await Hive.openBox('animestream'); 9 | if (!box.isOpen) box = await Hive.openBox('animestream'); 10 | Map settings = await box.get(HiveKey.settings.name) ?? {}; 11 | if (settings.isEmpty) settings = SettingsModal().toMap(); 12 | final classed = SettingsModal.fromMap(settings); 13 | if (!writing) await box.close(); 14 | return classed; 15 | } 16 | 17 | Future writeSettings(SettingsModal settings) async { 18 | var box = await Hive.openBox('animestream'); 19 | if (!box.isOpen) box = await Hive.openBox('animestream'); 20 | var currentSettings = (await getSettings(writing: true)).toMap(); 21 | var updatedSettings = settings.toMap(); 22 | print("before updation: $currentSettings"); 23 | print("value upation: $updatedSettings"); 24 | currentSettings.forEach((key, value) { 25 | if (updatedSettings[key] != null) { 26 | currentSettings[key] = updatedSettings[key]; 27 | } 28 | }); 29 | currentUserSettings = SettingsModal.fromMap(currentSettings); 30 | await box.put(HiveKey.settings.name, currentSettings); 31 | if (box.isOpen) await box.close; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/core/data/theme.dart: -------------------------------------------------------------------------------- 1 | import 'package:hive/hive.dart'; 2 | 3 | Future getTheme() async { 4 | var box = await Hive.openBox("animestream"); 5 | if (!box.isOpen) { 6 | box = await Hive.openBox("animestream"); 7 | } 8 | dynamic selectedThemeId = box.get('theme', defaultValue: 01) ?? 01; 9 | if (selectedThemeId == null || !(selectedThemeId is int)) selectedThemeId = 01; 10 | await box.close(); 11 | return selectedThemeId; 12 | } 13 | 14 | //saves the theme 15 | Future setTheme(int themeId) async { 16 | var box = await Hive.openBox("animestream"); 17 | if (!box.isOpen) { 18 | box = await Hive.openBox("animestream"); 19 | } 20 | await box.put('theme', themeId); 21 | await box.close(); 22 | return; 23 | } 24 | -------------------------------------------------------------------------------- /lib/core/database/anilist/login.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/commons/enums.dart'; 2 | import 'package:animestream/core/data/secureStorage.dart'; 3 | import 'package:animestream/core/database/anilist/anilist.dart'; 4 | import 'package:animestream/core/database/anilist/types.dart'; 5 | import 'package:animestream/core/database/database.dart'; 6 | import 'package:flutter_web_auth_2/flutter_web_auth_2.dart'; 7 | 8 | class AniListLogin extends DatabaseLogin { 9 | String url = "https://anilist.co/api/v2/oauth/authorize?client_id=15179&response_type=token"; 10 | 11 | String _extractToken(String url) { 12 | final RegExp regExp = RegExp(r'access_token=(.*?)&token_type='); 13 | final match = regExp.firstMatch(url); 14 | if (match != null) { 15 | final token = match.group(1); 16 | if (token != null) return token; 17 | throw new Exception("ERR_COULDNT_EXTRACT_TOKEN"); 18 | } else { 19 | throw new Exception("ERR_COULDNT_EXTRACT_TOKEN"); 20 | } 21 | } 22 | 23 | /**Will only return bool (i hope) */ 24 | @override 25 | Future initiateLogin() async { 26 | final res = await FlutterWebAuth2.authenticate(url: url, callbackUrlScheme: "auth.animestream"); 27 | if (!res.contains("access_token")) { 28 | print("ERR_RECIEVED_AUTH_CODE_NULL"); 29 | return false; 30 | } else { 31 | await storeSecureVal(SecureStorageKey.anilistToken, _extractToken(res)); 32 | return true; 33 | } 34 | // final nav = Navigator.push( 35 | // context, 36 | // MaterialPageRoute( 37 | // builder: (context) => WebView(url: url), 38 | // ), 39 | // ); 40 | // return nav; 41 | } 42 | 43 | Future removeToken() async { 44 | // await storeVal('token', null); 45 | await storeSecureVal(SecureStorageKey.anilistToken, null); 46 | } 47 | 48 | Future getUserProfile() async { 49 | final query = '''{ 50 | Viewer { 51 | id 52 | avatar { 53 | medium 54 | large 55 | } 56 | name 57 | bannerImage 58 | } 59 | }'''; 60 | 61 | // final String? token = await getVal("token"); 62 | final String? token = await getSecureVal(SecureStorageKey.anilistToken); 63 | if (token == null) throw new Exception("ERR_COULDNT_GET_TOKEN"); 64 | 65 | final res = await Anilist().fetchQuery(query, null, token: token); 66 | 67 | final data = res['Viewer']; 68 | return UserModal( 69 | id: data['id'], 70 | avatar: data['avatar']['large'] ?? data['avatar']['medium'], 71 | name: data['name'], 72 | banner: data['bannerImage']); 73 | } 74 | 75 | Future isAnilistLoggedIn() async { 76 | String? token; 77 | token = await getSecureVal(SecureStorageKey.anilistToken); 78 | if (token != null) return true; 79 | return false; 80 | } 81 | 82 | @override 83 | Future? refreshToken() { 84 | return null; //the access token is permanent 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /lib/core/database/anilist/mutations.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/commons/enums.dart'; 2 | import 'package:animestream/core/data/secureStorage.dart'; 3 | import 'package:animestream/core/database/anilist/anilist.dart'; 4 | import 'package:animestream/core/database/anilist/types.dart'; 5 | import 'package:animestream/core/database/database.dart'; 6 | 7 | class AnilistMutations extends DatabaseMutation { 8 | @override 9 | Future mutateAnimeList({ 10 | required int id, 11 | int? score, 12 | MediaStatus? status, 13 | int? progress, 14 | MediaStatus? previousStatus, 15 | }) async { 16 | final query = ''' 17 | mutation { 18 | SaveMediaListEntry(mediaId: $id, status: ${status?.name ?? MediaStatus.CURRENT.name}, progress: ${progress ?? 0}) { 19 | status 20 | progress 21 | } 22 | } 23 | '''; 24 | final res = 25 | await Anilist().fetchQuery(query, RequestType.mutate, token: await getSecureVal(SecureStorageKey.anilistToken)); 26 | return AnilistMutationResult( 27 | status: res?['SaveMediaListEntry']?['status'], progress: res?['SaveMediaListEntry']?['progress']); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/core/database/database.dart: -------------------------------------------------------------------------------- 1 | //contains base structure for a database 2 | 3 | import 'package:animestream/core/commons/enums.dart'; 4 | import 'package:animestream/core/database/types.dart'; 5 | 6 | enum Databases { 7 | anilist, 8 | mal, 9 | simkl; 10 | } 11 | 12 | class DatabaseFromString { 13 | static Databases getDb(String dbString) { 14 | switch (dbString) { 15 | case "anilist": 16 | return Databases.anilist; 17 | case "simkl": 18 | return Databases.simkl; 19 | case "mal": 20 | return Databases.mal; 21 | default: 22 | return Databases.anilist; 23 | } 24 | } 25 | } 26 | 27 | abstract class DatabaseLogin { 28 | Future initiateLogin(); 29 | Future removeToken(); 30 | Future? refreshToken(); 31 | } 32 | 33 | abstract class Database { 34 | Future> search(String query); 35 | 36 | Future getAnimeInfo(int id); 37 | } 38 | 39 | abstract class DatabaseMutation { 40 | Future mutateAnimeList( 41 | {required int id, MediaStatus? status = MediaStatus.CURRENT, int? progress = 0, MediaStatus? previousStatus}); 42 | } 43 | -------------------------------------------------------------------------------- /lib/core/database/handler/handler.dart: -------------------------------------------------------------------------------- 1 | //Call the database functions from this! 2 | 3 | import 'package:animestream/core/app/runtimeDatas.dart'; 4 | import 'package:animestream/core/database/anilist/anilist.dart'; 5 | import 'package:animestream/core/database/database.dart'; 6 | import 'package:animestream/core/database/mal/mal.dart'; 7 | import 'package:animestream/core/database/simkl/simkl.dart'; 8 | import 'package:animestream/core/database/types.dart'; 9 | 10 | class DatabaseHandler extends Database { 11 | DatabaseHandler({Databases? database}) { 12 | if (database != null) { 13 | this.db = database; 14 | } 15 | } 16 | 17 | Databases db = currentUserSettings?.database ?? Databases.anilist; 18 | 19 | static Database getDatabaseInstance(Databases dbs) { 20 | switch (dbs) { 21 | case Databases.anilist: 22 | return Anilist(); 23 | case Databases.simkl: 24 | return Simkl(); 25 | case Databases.mal: 26 | return MAL(); 27 | // default: 28 | // throw Exception("NOT_AN_OPTION_LIL_BRO"); 29 | } 30 | } 31 | 32 | @override 33 | Future> search(String query) async { 34 | return await getDatabaseInstance(db).search(query); 35 | } 36 | 37 | @override 38 | Future getAnimeInfo(int id) async { 39 | return await getDatabaseInstance(db).getAnimeInfo(id); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/core/database/handler/syncHandler.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/app/runtimeDatas.dart'; 2 | import 'package:animestream/core/commons/enums.dart'; 3 | import 'package:animestream/core/database/anilist/mutations.dart'; 4 | import 'package:animestream/core/database/database.dart'; 5 | import 'package:animestream/core/database/mal/mutations.dart'; 6 | import 'package:animestream/core/database/simkl/mutations.dart'; 7 | import 'package:animestream/core/database/types.dart'; 8 | 9 | class SyncHandler extends DatabaseMutation { 10 | @override 11 | Future mutateAnimeList({ 12 | required int id, 13 | List? otherIds, 14 | MediaStatus? status, 15 | MediaStatus? previousStatus, 16 | int? progress, 17 | }) async { 18 | final List databases = Databases.values; 19 | final activedb = getActiveDatabase(); 20 | final activeDbInstance = getDatabaseMutationInstance(activedb); 21 | 22 | //sync with the active database first 23 | activeDbInstance 24 | .mutateAnimeList(id: id, status: status, previousStatus: previousStatus, progress: progress) 25 | .then((val) => print("[SYNC HANDLER]: Synced ${activedb.name}")) 26 | .catchError((e, st) { 27 | print(e); 28 | print(st.toString()); 29 | return null; 30 | }); 31 | 32 | //sync with other databases 33 | otherIds?.forEach((it) { 34 | if (it.database != activedb) { 35 | final altdb = databases.where((db) => db == it.database).firstOrNull; 36 | if (altdb != null) { 37 | final mutInstance = getDatabaseMutationInstance(altdb); 38 | mutInstance 39 | .mutateAnimeList(id: it.id, status: status, previousStatus: previousStatus, progress: progress) 40 | .then((val) => print("[SYNC HANDLER]: Synced ${it.database.name}")) 41 | .catchError((e, st) { 42 | print(e); 43 | print(st.toString()); 44 | return null; 45 | }); 46 | } 47 | } 48 | }); 49 | 50 | return null; 51 | } 52 | 53 | DatabaseMutation getDatabaseMutationInstance(Databases db) { 54 | switch (db) { 55 | case Databases.anilist: 56 | return AnilistMutations(); 57 | case Databases.simkl: 58 | return SimklMutation(); 59 | case Databases.mal: 60 | return MALMutation(); 61 | // default: 62 | // throw Exception("NOT_AN_OPTION_LIL_BRO"); 63 | } 64 | } 65 | 66 | //get the preferred/current database 67 | Databases getActiveDatabase() { 68 | return currentUserSettings?.database ?? Databases.anilist; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /lib/core/database/mal/mal.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/commons/enums.dart'; 2 | import 'package:animestream/core/data/secureStorage.dart'; 3 | import 'package:animestream/core/database/database.dart'; 4 | import 'package:animestream/core/database/mal/login.dart'; 5 | import 'package:animestream/core/database/types.dart'; 6 | import 'package:http/http.dart'; 7 | 8 | class MAL extends Database { 9 | @override 10 | Future getAnimeInfo(int id) { 11 | // TODO: implement getAnimeInfo 12 | throw UnimplementedError(); 13 | } 14 | 15 | @override 16 | Future> search(String query) { 17 | // TODO: implement search 18 | throw UnimplementedError(); 19 | } 20 | 21 | static Map? headers = null; 22 | 23 | static Future> getHeader({bool refreshHeaders = false}) async { 24 | if(headers != null && !refreshHeaders) return headers!; 25 | final token = await getSecureVal(SecureStorageKey.malToken); 26 | final map = { 27 | 'Authorization': "Bearer ${token}", 28 | }; 29 | headers = map; 30 | return map; 31 | } 32 | 33 | Future fetch(String url, {int recallAttempt = 0, bool refreshHeaders = false }) async { 34 | 35 | if(recallAttempt > 2) throw Exception("MAX RECALL DEPTH LIMIT REACHED!"); 36 | 37 | final headers = await getHeader(refreshHeaders: refreshHeaders); 38 | final res = await get(Uri.parse(url), headers: headers); 39 | 40 | print(res.statusCode); 41 | 42 | if(res.statusCode == 401) { 43 | await MALLogin().refreshToken(); 44 | return await fetch(url, recallAttempt: recallAttempt+1, refreshHeaders: true); 45 | } 46 | 47 | //might have to remove this! 48 | if(res.statusCode != 200) { 49 | throw Exception("SOMETHING WRONG HAPPENED WHILE FETCHING MAL"); 50 | } 51 | 52 | return res.body; 53 | } 54 | } -------------------------------------------------------------------------------- /lib/core/database/mal/mutations.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/commons/enums.dart'; 2 | import 'package:animestream/core/database/database.dart'; 3 | import 'package:animestream/core/database/mal/login.dart'; 4 | import 'package:animestream/core/database/mal/mal.dart'; 5 | import 'package:animestream/core/database/mal/types.dart'; 6 | import 'package:http/http.dart'; 7 | 8 | class MALMutation extends DatabaseMutation { 9 | @override 10 | Future mutateAnimeList( 11 | {required int id, 12 | MediaStatus? status = MediaStatus.CURRENT, 13 | int? progress = 0, 14 | MediaStatus? previousStatus}) async { 15 | final url = "https://api.myanimelist.net/v2/anime/$id/my_list_status"; 16 | final body = {'status': stringifyMediaStatus(status!), 'num_watched_episodes': '$progress'}; 17 | final header = { 18 | ...(await MAL.getHeader()), 19 | 'Content-Type': 'application/x-www-form-urlencoded', 20 | }; 21 | final res = await put( 22 | Uri.parse(url), 23 | headers: header, 24 | body: body, 25 | ); 26 | print(res.statusCode); 27 | if (res.statusCode == 401) { 28 | // Retry after refreshing token 29 | await MALLogin().refreshToken(); 30 | final header = { 31 | ...(await MAL.getHeader(refreshHeaders: true)), 32 | 'Content-Type': 'application/x-www-form-urlencoded', 33 | }; 34 | await put( 35 | Uri.parse(url), 36 | headers: header, 37 | body: body, 38 | ); 39 | } 40 | return MALMutationResult(); 41 | } 42 | 43 | String stringifyMediaStatus(MediaStatus ms) { 44 | switch (ms) { 45 | case MediaStatus.COMPLETED: 46 | return "completed"; 47 | case MediaStatus.CURRENT: 48 | return "watching"; 49 | case MediaStatus.PAUSED: 50 | return "on_hold"; 51 | case MediaStatus.DROPPED: 52 | return "dropped"; 53 | case MediaStatus.PLANNING: 54 | return "plan_to_watch"; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /lib/core/database/mal/types.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: public_member_api_docs, sort_constructors_first 2 | import 'dart:convert'; 3 | 4 | import 'package:animestream/core/database/types.dart'; 5 | 6 | class MALAuthResponse { 7 | String accessToken; 8 | int expires_in; 9 | String refreshToken; 10 | 11 | MALAuthResponse({ 12 | required this.accessToken, required this.expires_in, required this.refreshToken, 13 | }); 14 | 15 | Map toMap() { 16 | return { 17 | 'access_token': accessToken, 18 | 'expires_in': expires_in, 19 | 'refresh_token': refreshToken, 20 | }; 21 | } 22 | 23 | factory MALAuthResponse.fromMap(Map map) { 24 | return MALAuthResponse( 25 | accessToken: map['access_token'] as String, 26 | expires_in: map['expires_in'] as int, 27 | refreshToken: map['refresh_token'] as String, 28 | ); 29 | } 30 | 31 | String toJson() => json.encode(toMap()); 32 | 33 | factory MALAuthResponse.fromJson(String source) => MALAuthResponse.fromMap(json.decode(source) as Map); 34 | } 35 | 36 | class MALMutationResult extends DatabaseMutationResult { 37 | //idk 38 | } 39 | -------------------------------------------------------------------------------- /lib/core/database/simkl/simkl.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:animestream/core/app/runtimeDatas.dart'; 4 | import 'package:animestream/core/database/database.dart'; 5 | import 'package:animestream/core/database/simkl/types.dart'; 6 | import 'package:http/http.dart'; 7 | 8 | class Simkl extends Database { 9 | static String imageLink(String url, {bool fanart = false}) => "https://wsrv.nl/?url=https://simkl.in/${fanart ? "fanart" : "posters"}/${url}${fanart ? "_w" : "_ca"}.webp"; 10 | 11 | Future> search(String query) async { 12 | final url = "https://api.simkl.com/search/anime?q=$query&client_id=$simklClientId"; 13 | final List res = await fetch(url); 14 | List sr = []; 15 | res.forEach((it) { 16 | sr.add(SimklSearchResult( 17 | cover: imageLink(it['poster']), 18 | id: it['ids']['simkl_id'], 19 | title: {'english': it['title_en'] ?? it['title'], 'romaji': it['title_romaji'] ?? it['title']}, 20 | )); 21 | }); 22 | 23 | return sr; 24 | } 25 | 26 | Future getAnimeInfo(int id) async { 27 | final url = "https://api.simkl.com/anime/$id?extended=full&client_id=$simklClientId"; 28 | final res = await fetch(url); 29 | final datafied = SimklInfo.fromJson(res); 30 | return datafied; 31 | } 32 | 33 | Future fetch(String url) async { 34 | final res = await get(Uri.parse(url)); 35 | 36 | //since 2** means success 37 | if (res.statusCode < 200 || res.statusCode > 299) { 38 | throw Exception("ERR_COULDNT_FETCH_SIMKL"); 39 | } 40 | return jsonDecode(res.body); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/core/database/types.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/database/database.dart'; 2 | 3 | abstract class DatabaseSearchResult { 4 | int get id; 5 | Map get title; 6 | String get cover; 7 | double? rating; 8 | } 9 | 10 | abstract class DatabaseRelatedRecommendation { 11 | int get id; 12 | Map get title; 13 | String get cover; 14 | String get type; 15 | double? rating; 16 | String? relationType; 17 | } 18 | 19 | class AlternateDatabaseId { 20 | Databases database; 21 | int id; 22 | 23 | AlternateDatabaseId({ 24 | required this.database, 25 | required this.id, 26 | }); 27 | } 28 | 29 | abstract class DatabaseMutationResult { 30 | String? status; 31 | int? progress; 32 | } 33 | 34 | abstract class DatabaseInfo { 35 | Map get title; 36 | Map get aired; 37 | String? get banner; 38 | String get cover; 39 | String get duration; 40 | int? get episodes; 41 | List get genres; 42 | List> get characters; 43 | Object? nextAiringEpisode; 44 | double? rating; 45 | List get recommended; 46 | List get related; 47 | String? get status; 48 | String get type; 49 | List get studios; 50 | List get synonyms; 51 | String? get synopsis; 52 | List? tags; 53 | String? mediaListStatus; 54 | List get alternateDatabases; 55 | } 56 | -------------------------------------------------------------------------------- /lib/core/news/animenews.dart: -------------------------------------------------------------------------------- 1 | import "package:http/http.dart"; 2 | import "package:html/parser.dart" as html; 3 | 4 | class AnimeNews { 5 | final String _baseUrl = 'https://animenewsnetwork.com'; 6 | 7 | final String _cdnUrl = 'https://cdn.animenewsnetwork.com'; 8 | 9 | Future> getDetailedNews(String url) async { 10 | final res = await fetch(url); 11 | final document = html.parse(res); 12 | final pageTitle = document.querySelector("div#page-title > h1#page_header")?.text.replaceAll(RegExp(r'News'), '').replaceAll(r'\n| {2,}', '').trim(); 13 | final postedOn = document.querySelector('div#page-title > small')?.text.trim(); 14 | final postedBy = document.querySelector('div#page-title')?.text.replaceAll(RegExp(r'n| {2,}'), '').split('by')[1].trim(); 15 | final captions = document.querySelectorAll('figcaption'); 16 | for(final caption in captions) { 17 | caption.remove(); 18 | } 19 | final details = document.querySelector('div.text-zone.easyread-width > div.KonaBody > div.meat'); 20 | final image = details?.querySelector('figure > img')?.attributes['data-src'] != null ? _cdnUrl + (details?.querySelector('figure > img')?.attributes['data-src'] ?? '') : null; 21 | final List texts = []; 22 | details?.children.forEach((element) { 23 | texts.add(element.text.trim()); 24 | }); 25 | return { 26 | 'title': pageTitle, 27 | 'postedOn': postedOn, 28 | 'postedBy': postedBy, 29 | 'image': image, 30 | 'info': texts.join() 31 | }; 32 | } 33 | 34 | Future>> getNewses() async { 35 | final url = _baseUrl + '/news'; 36 | final res = await fetch(url); 37 | final document = html.parse(res); 38 | final List> newses = []; 39 | document.querySelectorAll('.herald.box.news.t-news').forEach((element) { 40 | final src = element.querySelector('.thumbnail')?.attributes['data-src']; 41 | final image = src != null ? _cdnUrl + src : null; 42 | final wrapDiv = element.querySelector('.wrap > div'); 43 | final titleElement = wrapDiv?.querySelector('h3')?.children[0] ?? null; 44 | final ref = titleElement?.attributes['href'] != null ? url + (titleElement?.attributes['href'] ?? '') : null; 45 | final title = titleElement?.text.trim(); 46 | final dateAndTime = wrapDiv?.querySelector('time')?.attributes['datetime']; 47 | final dateSplit = dateAndTime?.split('T')[0].split('-'); 48 | final date = "${dateSplit?[2] ?? null}-${dateSplit?[1] ?? null}-${dateSplit?[0] ?? null}"; 49 | final time = dateAndTime?.split('T')[1].split(RegExp(r'\+|\-'))[0]; 50 | final topic = wrapDiv?.querySelector('.topics > a')?.attributes['topic']; 51 | final snippet = wrapDiv?.querySelector('.snippet > span.full')?.text; 52 | newses.add({ 53 | 'image': image, 54 | 'title': title, 55 | 'url': ref, 56 | 'date': date, 57 | 'time': time, 58 | 'category': topic, 59 | 'snippet': snippet 60 | }); 61 | }); 62 | 63 | return newses; 64 | } 65 | 66 | Future fetch(String url) async { 67 | final res = await get(Uri.parse(url)); 68 | return res.body; 69 | } 70 | } -------------------------------------------------------------------------------- /lib/ui/models/extensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | extension ColorExtensions on Color { 4 | String toHexString() { 5 | final alpha = (this.a * 255).toInt(); 6 | final red = (this.r * 255).toInt(); 7 | final green = (this.g * 255).toInt(); 8 | final blue = (this.b * 255).toInt(); 9 | 10 | return "${alpha.toRadixString(16).padLeft(2,'0')}${red.toRadixString(16).padLeft(2,'0')}${green.toRadixString(16).padLeft(2,'0')}${blue.toRadixString(16).padLeft(2,'0')}"; 11 | } 12 | 13 | /**Returns the integer representation of the color */ 14 | int toInt() { 15 | final alpha = (this.a * 255).toInt(); 16 | final red = (this.r * 255).toInt(); 17 | final green = (this.g * 255).toInt(); 18 | final blue = (this.b * 255).toInt(); 19 | return (alpha << 24) | (red << 16) | (green << 8) | blue; 20 | } 21 | } 22 | 23 | extension StringExtensions on String { 24 | String capitalize() { 25 | if(this.length < 1) return ""; 26 | return this.replaceFirst(this[0], this[0].toUpperCase()); 27 | } 28 | 29 | String capitalizeAllWords({String delimiter = " "}) { 30 | final words = this.split(delimiter); 31 | List newString = []; 32 | for(final word in words) { 33 | newString.add(word.capitalize()); 34 | } 35 | return newString.join(" "); 36 | } 37 | 38 | Uri? toUri() { 39 | return Uri.tryParse(this); 40 | } 41 | } -------------------------------------------------------------------------------- /lib/ui/models/snackBar.dart: -------------------------------------------------------------------------------- 1 | import "dart:io"; 2 | 3 | import "package:animestream/main.dart"; 4 | import "package:flutter/material.dart"; 5 | import "package:flutter/services.dart"; 6 | 7 | void floatingSnackBar(String message, {int? duration, bool waitForPreviousToFinish = false}) { 8 | final isWindows = Platform.isWindows; 9 | if (!waitForPreviousToFinish) AnimeStream.snackbarKey.currentState?.removeCurrentSnackBar(); 10 | AnimeStream.snackbarKey.currentState?.showSnackBar( 11 | SnackBar( 12 | content: Center( 13 | child: Text(message, style: TextStyle(fontFamily: "NotoSans", color: Colors.white, fontSize: 14)), 14 | ), 15 | duration: Duration(seconds: duration != null ? duration : 3), 16 | backgroundColor: Color.fromARGB(244, 26, 26, 26), 17 | behavior: SnackBarBehavior.floating, 18 | dismissDirection: DismissDirection.down, 19 | margin: isWindows ? null : EdgeInsets.only(bottom: 40, left: 20, right: 20), 20 | width: isWindows ? MediaQuery.of(AnimeStream.snackbarKey.currentState!.context).size.width / 5 : null, 21 | shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), 22 | ), 23 | ); 24 | } 25 | 26 | void showToast(String message) async { 27 | final platform = MethodChannel('animestream.app/utils'); 28 | await platform.invokeMethod("showToast", {'message': message}); 29 | } 30 | -------------------------------------------------------------------------------- /lib/ui/models/widgets/clickableItem.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/app/runtimeDatas.dart'; 2 | import 'package:animestream/ui/pages/settingPages/common.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | // Represents the button tiles which are clickable in setting screen 6 | class ClickableItem extends StatelessWidget { 7 | final VoidCallback onTap; 8 | final String label; 9 | final String? description; 10 | final Icon? suffixIcon; 11 | final EdgeInsets? contentPadding; 12 | const ClickableItem({ 13 | super.key, 14 | required this.onTap, 15 | required this.label, 16 | this.description, 17 | this.suffixIcon, 18 | this.contentPadding = const EdgeInsets.only(left: 20, right: 20, top: 10, bottom: 10), 19 | }); 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return InkWell( 24 | onTap: onTap, 25 | child: Container( 26 | padding: contentPadding, 27 | width: double.infinity, 28 | child: Row( 29 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 30 | children: [ 31 | Container( 32 | child: Column( 33 | crossAxisAlignment: CrossAxisAlignment.start, 34 | children: [ 35 | Text( 36 | label, 37 | style: textStyle(), 38 | ), 39 | if (description != null) 40 | Text( 41 | description!, 42 | style: textStyle().copyWith(color: appTheme.textSubColor, fontSize: 12), 43 | ), 44 | ], 45 | ), 46 | ), 47 | if (suffixIcon != null) suffixIcon!, 48 | ], 49 | ), 50 | ), 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/ui/models/widgets/header.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/app/runtimeDatas.dart'; 2 | import 'package:animestream/ui/pages/settings.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | Container buildHeader(String title, BuildContext context, { void Function()? afterNavigation}) { 6 | return Container( 7 | padding: EdgeInsets.only(left: 20, top: 10, right: 20, bottom: 20), 8 | child: Row( 9 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 10 | children: [ 11 | Text( 12 | title, 13 | style: TextStyle( 14 | color: appTheme.textMainColor, 15 | fontFamily: "Rubik", 16 | fontWeight: FontWeight.bold, 17 | fontSize: 30, 18 | ), 19 | ), 20 | IconButton( 21 | onPressed: () => Navigator.of(context).push( 22 | MaterialPageRoute( 23 | builder: (context) => SettingsPage(), 24 | ), 25 | ).then((value) { 26 | if(afterNavigation != null) 27 | afterNavigation(); 28 | },), 29 | icon: Icon( 30 | Icons.settings_rounded, 31 | color: appTheme.textMainColor, 32 | size: 32, 33 | ), 34 | ), 35 | ], 36 | ), 37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /lib/ui/models/widgets/loader.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'dart:math' as math; 3 | import 'package:flutter/material.dart'; 4 | 5 | // HMM used an AI, Im just a vibe coder atp ig 6 | class AnimeStreamLoading extends StatefulWidget { 7 | final Color color; 8 | final double size; 9 | final Duration duration; 10 | 11 | const AnimeStreamLoading({ 12 | Key? key, 13 | this.color = Colors.purple, 14 | this.size = 80.0, 15 | this.duration = const Duration(milliseconds: 1800), 16 | }) : super(key: key); 17 | 18 | @override 19 | _AnimeStreamLoadingState createState() => _AnimeStreamLoadingState(); 20 | } 21 | 22 | class _AnimeStreamLoadingState extends State 23 | with SingleTickerProviderStateMixin { 24 | late AnimationController _controller; 25 | 26 | @override 27 | void initState() { 28 | super.initState(); 29 | _controller = AnimationController( 30 | vsync: this, 31 | duration: widget.duration, 32 | )..repeat(); 33 | } 34 | 35 | @override 36 | void dispose() { 37 | _controller.dispose(); 38 | super.dispose(); 39 | } 40 | 41 | @override 42 | Widget build(BuildContext context) { 43 | return SizedBox( 44 | width: widget.size, 45 | height: widget.size, 46 | child: AnimatedBuilder( 47 | animation: _controller, 48 | builder: (context, child) { 49 | return CustomPaint( 50 | painter: _SimpleAnimePainter( 51 | color: widget.color, 52 | animation: _controller, 53 | ), 54 | ); 55 | }, 56 | ), 57 | ); 58 | } 59 | } 60 | 61 | class _SimpleAnimePainter extends CustomPainter { 62 | final Color color; 63 | final Animation animation; 64 | 65 | _SimpleAnimePainter({ 66 | required this.color, 67 | required this.animation, 68 | }); 69 | 70 | @override 71 | void paint(Canvas canvas, Size size) { 72 | if (size.width <= 0 || size.height <= 0) return; 73 | 74 | final center = Offset(size.width / 2, size.height / 2); 75 | final radius = math.min(size.width, size.height) / 2; 76 | 77 | for (int i = 0; i < 3; i++) { 78 | final angle = animation.value * math.pi * 2 + (i * 2 * math.pi / 3); 79 | final orbitRadius = radius * 0.6; 80 | final x = center.dx + orbitRadius * math.cos(angle); 81 | final y = center.dy + orbitRadius * math.sin(angle); 82 | 83 | final pulseFactor = 0.6 + 0.4 * math.sin(animation.value * math.pi * 2 + i * math.pi * 2 / 3); 84 | final dotRadius = radius * 0.15 * pulseFactor; 85 | 86 | final alpha = (179 + 76 * pulseFactor).toInt().clamp(0, 255); 87 | 88 | final paint = Paint() 89 | ..color = color.withAlpha(alpha) 90 | ..style = PaintingStyle.fill; 91 | 92 | canvas.drawCircle(Offset(x, y), dotRadius, paint); 93 | } 94 | 95 | final centerPulseFactor = 0.8 + 0.2 * math.sin(animation.value * math.pi * 4); 96 | final centerPaint = Paint() 97 | ..color = color.withAlpha((128 * centerPulseFactor).toInt().clamp(0, 255)) 98 | ..style = PaintingStyle.fill; 99 | 100 | canvas.drawCircle(center, radius * 0.25 * centerPulseFactor, centerPaint); 101 | 102 | final ringPaint = Paint() 103 | ..color = color.withAlpha(76) 104 | ..style = PaintingStyle.stroke 105 | ..strokeWidth = 1.0; 106 | 107 | canvas.drawCircle(center, radius * 0.6, ringPaint); 108 | } 109 | 110 | @override 111 | bool shouldRepaint(_SimpleAnimePainter oldDelegate) { 112 | return true; 113 | } 114 | } -------------------------------------------------------------------------------- /lib/ui/models/widgets/player/playerUtils.dart: -------------------------------------------------------------------------------- 1 | import 'package:better_player/better_player.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | BetterPlayerDataSource dataSourceConfig(String url, {Map? headers = null}) { 5 | return BetterPlayerDataSource( 6 | BetterPlayerDataSourceType.network, 7 | url, 8 | bufferingConfiguration: BetterPlayerBufferingConfiguration( 9 | maxBufferMs: 120000, 10 | ), 11 | cacheConfiguration: BetterPlayerCacheConfiguration( 12 | useCache: true, 13 | maxCacheFileSize: 50 * 1024 * 1024, 14 | maxCacheSize: 50 * 1024 * 1024, 15 | ), 16 | headers: headers, 17 | placeholder: PlayerLoadingWidget(), 18 | ); 19 | } 20 | 21 | class PlayerLoadingWidget extends StatelessWidget { 22 | const PlayerLoadingWidget({ 23 | super.key, 24 | }); 25 | 26 | @override 27 | Widget build(BuildContext context) { 28 | return Center( 29 | child: Column( 30 | mainAxisAlignment: MainAxisAlignment.center, 31 | mainAxisSize: MainAxisSize.min, 32 | children: [ 33 | Container( 34 | height: 200, 35 | width: 200, 36 | child: Image.asset( 37 | "lib/assets/icons/logo_foreground.png", 38 | opacity: AlwaysStoppedAnimation(0.6), 39 | )), 40 | Text( 41 | "Loading Your Anime...", 42 | style: TextStyle(color: Colors.grey, fontFamily: "Rubik", fontWeight: FontWeight.bold), 43 | ) 44 | ], 45 | ), 46 | ); 47 | } 48 | } 49 | 50 | /**Format seconds to hour:min:sec format */ 51 | String getFormattedTime(int timeInSeconds) { 52 | String formatTime(int val) { 53 | return val.toString().padLeft(2, '0'); 54 | } 55 | 56 | int hours = timeInSeconds ~/ 3600; 57 | int minutes = (timeInSeconds % 3600) ~/ 60; 58 | int seconds = timeInSeconds % 60; 59 | 60 | String formattedHours = hours == 0 ? '' : formatTime(hours); 61 | String formattedMins = formatTime(minutes); 62 | String formattedSeconds = formatTime(seconds); 63 | 64 | return "${formattedHours.length > 0 ? "$formattedHours:" : ''}$formattedMins:$formattedSeconds"; 65 | } 66 | -------------------------------------------------------------------------------- /lib/ui/models/widgets/sourceTile.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/anime/providers/types.dart'; 2 | import 'package:animestream/core/app/runtimeDatas.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class SourceTile extends StatefulWidget { 6 | final VideoStream source; 7 | final VoidCallback onTap; 8 | const SourceTile({ 9 | super.key, 10 | required this.source, 11 | required this.onTap, 12 | }); 13 | 14 | @override 15 | State createState() => _SourceTileState(); 16 | } 17 | 18 | class _SourceTileState extends State { 19 | bool hovered = false; 20 | @override 21 | Widget build(BuildContext context) { 22 | return Padding( 23 | padding: EdgeInsets.only(bottom: 10), 24 | child: InkWell( 25 | onTap: widget.onTap, 26 | splashColor: Colors.transparent, 27 | splashFactory: NoSplash.splashFactory, 28 | onHover: (val) { 29 | setState(() => hovered = val); 30 | }, 31 | borderRadius: BorderRadius.circular(15), 32 | child: AnimatedContainer( 33 | duration: Duration(milliseconds: 100), 34 | padding: EdgeInsets.symmetric(vertical: 14, horizontal: 20), 35 | decoration: BoxDecoration( 36 | color: hovered ? appTheme.backgroundSubColor.withAlpha(242) : appTheme.backgroundSubColor, 37 | borderRadius: BorderRadius.circular(15), 38 | border: Border.all( 39 | color: hovered ? appTheme.accentColor.withAlpha(178) : Colors.transparent, 40 | width: 1.5, 41 | ), 42 | boxShadow: [ 43 | BoxShadow( 44 | color: Colors.black.withAlpha(38), 45 | blurRadius: 12, 46 | offset: Offset(0, 6), 47 | ), 48 | ], 49 | ), 50 | child: Row( 51 | children: [ 52 | Icon(Icons.video_library_rounded, color: appTheme.accentColor, size: 24), 53 | SizedBox(width: 12), 54 | Expanded( 55 | child: Column( 56 | crossAxisAlignment: CrossAxisAlignment.start, 57 | children: [ 58 | Text( 59 | widget.source.server, 60 | style: TextStyle( 61 | fontSize: 16, 62 | fontWeight: FontWeight.bold, 63 | color: appTheme.textMainColor, 64 | ), 65 | ), 66 | SizedBox(height: 4), 67 | Text( 68 | "${widget.source.quality} ${widget.source.backup ? '• Backup' : ''}", 69 | style: TextStyle( 70 | fontSize: 14, 71 | color: appTheme.textSubColor, 72 | ), 73 | ), 74 | ], 75 | ), 76 | ), 77 | Icon(Icons.chevron_right, color: appTheme.textSubColor), 78 | ], 79 | ), 80 | ), 81 | ), 82 | ); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /lib/ui/models/widgets/subtitles/subtitle.dart: -------------------------------------------------------------------------------- 1 | class Subtitle { 2 | final Duration start; 3 | final Duration end; 4 | final String dialogue; 5 | 6 | Subtitle({ 7 | required this.dialogue, 8 | required this.end, 9 | required this.start, 10 | }); 11 | 12 | @override 13 | String toString() => 'Subtitle(start: $start, end: $end, dialogue: $dialogue)'; 14 | } -------------------------------------------------------------------------------- /lib/ui/models/widgets/subtitles/subtitleSettings.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:animestream/ui/models/extensions.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | class SubtitleSettings { 7 | final Color textColor; 8 | final Color strokeColor; 9 | final Color backgroundColor; 10 | 11 | final String? fontFamily; 12 | 13 | final double strokeWidth; 14 | final double fontSize; 15 | final double bottomMargin; 16 | final double backgroundTransparency; 17 | 18 | final bool bold; 19 | final bool enableShadows; 20 | 21 | SubtitleSettings({ 22 | this.backgroundColor = Colors.black, 23 | this.backgroundTransparency = 0, 24 | this.bottomMargin = 30, 25 | this.fontSize = 24, 26 | this.strokeColor = Colors.black, 27 | this.strokeWidth = 2, 28 | this.textColor = Colors.white, 29 | this.fontFamily = "Rubik", 30 | this.bold = false, 31 | this.enableShadows = true, 32 | }); 33 | 34 | SubtitleSettings copyWith({ 35 | Color? textColor, 36 | Color? strokeColor, 37 | Color? backgroundColor, 38 | String? fontFamily, 39 | double? strokeWidth, 40 | double? fontSize, 41 | double? bottomMargin, 42 | double? backgroundTransparency, 43 | bool? bold, 44 | bool? enableShadows, 45 | }) { 46 | return SubtitleSettings( 47 | textColor: textColor ?? this.textColor, 48 | strokeColor: strokeColor ?? this.strokeColor, 49 | backgroundColor: backgroundColor ?? this.backgroundColor, 50 | fontFamily: fontFamily ?? this.fontFamily, 51 | strokeWidth: strokeWidth ?? this.strokeWidth, 52 | fontSize: fontSize ?? this.fontSize, 53 | bottomMargin: bottomMargin ?? this.bottomMargin, 54 | backgroundTransparency: backgroundTransparency ?? this.backgroundTransparency, 55 | bold: bold ?? this.bold, 56 | enableShadows: enableShadows ?? this.enableShadows, 57 | ); 58 | } 59 | 60 | Map toMap() { 61 | return { 62 | 'textColor': textColor.toInt(), 63 | 'strokeColor': strokeColor.toInt(), 64 | 'backgroundColor': backgroundColor.toInt(), 65 | 'fontFamily': fontFamily, 66 | 'strokeWidth': strokeWidth, 67 | 'fontSize': fontSize, 68 | 'bottomMargin': bottomMargin, 69 | 'backgroundTransparency': backgroundTransparency, 70 | 'bold': bold, 71 | 'enableShadows': enableShadows, 72 | }; 73 | } 74 | 75 | factory SubtitleSettings.fromMap(Map map) { 76 | return SubtitleSettings( 77 | textColor: Color(map['textColor'] as int? ?? Colors.white.toInt()), 78 | strokeColor: Color(map['strokeColor'] as int? ?? Colors.black.toInt()), 79 | backgroundColor: Color((map['backgroundColor'] ?? Colors.black.toInt()) as int), 80 | fontFamily: map['fontFamily'] != null ? map['fontFamily'] as String : "Rubik", 81 | strokeWidth: (map['strokeWidth'] ?? 1.1) as double, 82 | fontSize: (map['fontSize'] ?? 24) as double, 83 | bottomMargin: (map['bottomMargin'] ?? 30) as double, 84 | backgroundTransparency: (map['backgroundTransparency'] ?? 0) as double, 85 | bold: (map['bold'] ?? false) as bool, 86 | enableShadows: (map['enableShadows'] ?? true) as bool); 87 | } 88 | 89 | String toJson() => json.encode(toMap()); 90 | 91 | factory SubtitleSettings.fromJson(String source) => 92 | SubtitleSettings.fromMap(json.decode(source) as Map); 93 | } -------------------------------------------------------------------------------- /lib/ui/models/widgets/subtitles/subtitleText.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class SubtitleText extends StatelessWidget { 4 | final String text; 5 | final TextStyle style; 6 | final Color strokeColor; 7 | final Color backgroundColor; 8 | final double strokeWidth; 9 | final double backgroundTransparency; 10 | final bool enableShadows; 11 | 12 | const SubtitleText({ 13 | super.key, 14 | required this.text, 15 | required this.style, 16 | required this.strokeColor, 17 | required this.strokeWidth, 18 | required this.backgroundColor, 19 | required this.backgroundTransparency, 20 | this.enableShadows = true, 21 | }); 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | return Container( 26 | color: backgroundColor.withAlpha((backgroundTransparency * 255).toInt()), 27 | child: Stack( 28 | children: [ 29 | //the stroke of that text since the flutter doesnt have it :( 30 | Text( 31 | text, 32 | style: style.copyWith( 33 | foreground: Paint() 34 | ..style = PaintingStyle.stroke 35 | ..color = strokeColor 36 | ..strokeWidth = strokeWidth, 37 | ), 38 | textAlign: TextAlign.center, 39 | ), 40 | 41 | //the actual text 42 | Text( 43 | text, 44 | style: style.copyWith( 45 | shadows: enableShadows 46 | ? [ 47 | Shadow(color: Colors.black, blurRadius: 3.5, offset: Offset(1, 1)), 48 | ] 49 | : null, 50 | ), 51 | textAlign: TextAlign.center, 52 | ), 53 | ], 54 | ), 55 | ); 56 | } 57 | } -------------------------------------------------------------------------------- /lib/ui/models/widgets/toggleItem.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/app/runtimeDatas.dart'; 2 | import 'package:animestream/ui/pages/settingPages/common.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class ToggleItem extends StatelessWidget { 6 | final VoidCallback onTapFunction; 7 | final String label; 8 | final String? description; 9 | final bool value; 10 | 11 | const ToggleItem({ 12 | super.key, 13 | required this.onTapFunction, 14 | required this.label, 15 | this.description, 16 | required this.value, 17 | }); 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | return InkWell( 22 | onTap: onTapFunction, 23 | child: Container( 24 | padding: EdgeInsets.only(top: 10, bottom: 10, left: 10, right: 10), 25 | child: Container( 26 | padding: EdgeInsets.only( 27 | left: 10, 28 | right: 10, 29 | ), 30 | child: Row( 31 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 32 | children: [ 33 | Column( 34 | crossAxisAlignment: CrossAxisAlignment.start, 35 | children: [ 36 | Text( 37 | label, 38 | style: textStyle(), 39 | ), 40 | if (description != null) 41 | Text( 42 | description!, 43 | style: textStyle().copyWith(color: appTheme.textSubColor, fontSize: 12), 44 | ), 45 | ], 46 | ), 47 | Switch( 48 | value: value, 49 | onChanged: (val) { 50 | onTapFunction(); 51 | }, 52 | activeColor: appTheme.backgroundColor, 53 | activeTrackColor: appTheme.accentColor, 54 | ) 55 | ], 56 | ), 57 | ), 58 | ), 59 | ); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/ui/pages/info.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:animestream/ui/models/providers/infoProvider.dart'; 4 | import 'package:animestream/ui/pages/info/infoDesktop.dart'; 5 | import 'package:animestream/ui/pages/info/infoMobile.dart'; 6 | import 'package:flutter/material.dart'; 7 | 8 | import 'package:provider/provider.dart'; 9 | 10 | class Info extends StatelessWidget { 11 | final int id; 12 | const Info({required this.id}); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return ChangeNotifierProvider( 17 | create: (context) => InfoProvider(id)..init(), 18 | builder: (context, child) { 19 | if (Platform.isWindows) 20 | return InfoDesktop(); 21 | else 22 | return InfoMobile(); 23 | }, 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/ui/pages/news.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/core/app/runtimeDatas.dart'; 2 | import 'package:animestream/core/news/animenews.dart'; 3 | import 'package:animestream/ui/models/widgets/cards.dart'; 4 | import 'package:animestream/ui/pages/newsDetail.dart'; 5 | import 'package:flutter/material.dart'; 6 | 7 | class News extends StatefulWidget { 8 | const News({super.key}); 9 | 10 | @override 11 | State createState() => _NewsState(); 12 | } 13 | 14 | class _NewsState extends State { 15 | List newses = []; 16 | bool loaded = false; 17 | 18 | @override 19 | void initState() { 20 | super.initState(); 21 | getNewses(); 22 | } 23 | 24 | Future getNewses() async { 25 | final List data = await AnimeNews().getNewses(); 26 | if (mounted) { 27 | setState(() { 28 | newses = data; 29 | loaded = true; 30 | }); 31 | } 32 | } 33 | 34 | @override 35 | Widget build(BuildContext context) { 36 | return Scaffold( 37 | backgroundColor: appTheme.backgroundColor, 38 | appBar: AppBar( 39 | leading: IconButton( 40 | onPressed: () => Navigator.of(context).pop(), 41 | icon: Icon(Icons.arrow_back_rounded, 42 | color: appTheme.textMainColor,), 43 | ), 44 | backgroundColor: appTheme.backgroundColor, 45 | title: Text( 46 | "News", 47 | style: TextStyle(color: appTheme.textMainColor, fontFamily: "Poppins", fontSize: 25), 48 | ), 49 | ), 50 | body: !loaded 51 | ? Center( 52 | child: CircularProgressIndicator( 53 | color: appTheme.accentColor, 54 | ), 55 | ) 56 | : SingleChildScrollView( 57 | child: Padding( 58 | padding: MediaQuery.of(context).padding.copyWith(top: 10), 59 | child: Column( 60 | children: [ 61 | // Container( 62 | // padding: EdgeInsets.only(top: 10, bottom: MediaQuery.of(context).padding.bottom), 63 | // child: Text( 64 | // "News", 65 | // style: TextStyle( 66 | // color: Colors.white, 67 | // fontFamily: "Poppins", 68 | // fontSize: 30), 69 | // ), 70 | // ), 71 | ListView.builder( 72 | shrinkWrap: true, 73 | itemCount: newses.length, 74 | physics: NeverScrollableScrollPhysics(), 75 | itemBuilder: (context, index) => GestureDetector( 76 | onTap: () { 77 | Navigator.of(context).push(MaterialPageRoute( 78 | builder: (context) => NewsDetails( 79 | url: newses[index]['url'], 80 | ))); 81 | }, 82 | child: Container( 83 | decoration: BoxDecoration(color: Colors.transparent), 84 | padding: EdgeInsets.only(top: 5, left: 10, right: 10), 85 | child: Cards.NewsCard(newses[index]['title'], newses[index]['image'], newses[index]['date'], 86 | newses[index]['time']), 87 | ), 88 | ), 89 | ) 90 | ], 91 | ), 92 | ), 93 | ), 94 | ); 95 | } 96 | 97 | @override 98 | void dispose() { 99 | super.dispose(); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /lib/ui/theme/amethyst.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/ui/theme/types.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class Amethyst implements ThemeItem { 5 | @override 6 | int get id => 05; 7 | 8 | @override 9 | AnimeStreamTheme get lightVariant => AnimeStreamTheme( 10 | accentColor: Color(0xff6a3b76), 11 | backgroundColor: Color(0xfff9efea), 12 | backgroundSubColor: Color(0xffbb8da3), 13 | textMainColor: Color(0xff2a1a2a), 14 | textSubColor: Color(0xff645055), 15 | modalSheetBackgroundColor: Color(0xfff4e9e4), 16 | onAccent: Color(0xfff9efea), 17 | ); 18 | 19 | @override 20 | String get name => "Amethyst"; 21 | 22 | @override 23 | AnimeStreamTheme get theme => AnimeStreamTheme( 24 | accentColor: Color(0xff6a3b76), 25 | backgroundColor: Color(0xff1a1119), 26 | backgroundSubColor: Color.fromARGB(255, 65, 37, 53), 27 | textMainColor: Color(0xfffdf0e6), // Slightly softened white 28 | textSubColor: Color(0xffe7c3bf), 29 | modalSheetBackgroundColor: Color(0xff1e0620), 30 | onAccent: Color(0xfffbf0e8), 31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /lib/ui/theme/coldPurple.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/ui/theme/types.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | /// Cold Purple Theme 5 | class ColdPurple implements ThemeItem { 6 | @override 7 | int get id => 03; 8 | 9 | @override 10 | AnimeStreamTheme get lightVariant => AnimeStreamTheme( 11 | accentColor: Color(0xff9D8ABF), 12 | backgroundColor: Colors.white, 13 | backgroundSubColor: Color.fromARGB(255, 179, 179, 179), 14 | textMainColor: Colors.black, 15 | textSubColor: Color.fromARGB(255, 82, 82, 82), 16 | modalSheetBackgroundColor: Colors.white, 17 | onAccent: Colors.white, 18 | ); 19 | 20 | @override 21 | String get name => "Cold Purple"; 22 | 23 | @override 24 | AnimeStreamTheme get theme => AnimeStreamTheme( 25 | accentColor: Color(0xff9D8ABF), 26 | backgroundColor: Color.fromARGB(255, 24, 24, 24), 27 | backgroundSubColor: const Color.fromARGB(255, 36, 36, 36), 28 | textMainColor: Colors.white, 29 | textSubColor: Color.fromARGB(255, 180, 180, 180), 30 | modalSheetBackgroundColor: Color(0xff121212), 31 | onAccent: Colors.black, 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /lib/ui/theme/hotPink.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/ui/theme/types.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class HotPink implements ThemeItem { 5 | @override 6 | int get id => 04; 7 | 8 | @override 9 | AnimeStreamTheme get lightVariant => AnimeStreamTheme( 10 | accentColor: Color.fromARGB(255, 255, 91, 173), 11 | backgroundColor: Colors.white, 12 | backgroundSubColor: Color.fromARGB(255, 179, 179, 179), 13 | textMainColor: Colors.black, 14 | textSubColor: Color.fromARGB(255, 82, 82, 82), 15 | modalSheetBackgroundColor: Colors.white, 16 | onAccent: Colors.white, 17 | ); 18 | 19 | @override 20 | String get name => "Hot Pink"; 21 | 22 | @override 23 | AnimeStreamTheme get theme => AnimeStreamTheme( 24 | accentColor: Color.fromARGB(255, 255, 91, 173), 25 | backgroundColor: Color.fromARGB(255, 24, 24, 24), 26 | backgroundSubColor: Color.fromARGB(255, 36, 36, 36), 27 | textMainColor: Colors.white, 28 | textSubColor: Color.fromARGB(255, 180, 180, 180), 29 | modalSheetBackgroundColor: Color(0xff121212), 30 | onAccent: Colors.black, 31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /lib/ui/theme/lime.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/ui/theme/types.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | /// The default theme 5 | class LimeZest implements ThemeItem { 6 | @override 7 | int get id => 01; 8 | 9 | @override 10 | String get name => "Lime Zest"; 11 | 12 | @override 13 | AnimeStreamTheme get lightVariant => AnimeStreamTheme( 14 | accentColor: Color(0xffcaf979), 15 | backgroundColor: Colors.white, 16 | textMainColor: Colors.black, 17 | textSubColor: Color.fromARGB(255, 82, 82, 82), 18 | modalSheetBackgroundColor: Colors.white, 19 | backgroundSubColor: Color.fromARGB(255, 179, 179, 179), 20 | onAccent: Colors.black, 21 | ); 22 | 23 | @override 24 | AnimeStreamTheme get theme => AnimeStreamTheme( 25 | accentColor: Color(0xffCAF979), 26 | backgroundColor: Color.fromARGB(255, 24, 24, 24), 27 | backgroundSubColor: Color.fromARGB(255, 36, 36, 36), 28 | textMainColor: Colors.white, 29 | textSubColor: Color.fromARGB(255, 180, 180, 180), 30 | modalSheetBackgroundColor: Color(0xff121212), 31 | onAccent: Colors.black, 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /lib/ui/theme/mocha.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/ui/theme/types.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class Mocha implements ThemeItem { 5 | @override 6 | int get id => 06; 7 | 8 | @override 9 | AnimeStreamTheme get lightVariant => AnimeStreamTheme( 10 | accentColor: Color(0xff8C7972), 11 | backgroundColor: Color(0xffF2F2F2), 12 | backgroundSubColor: Color.fromARGB(255, 190, 154, 131), 13 | textMainColor: Color(0xff261E18), 14 | textSubColor: Color.fromARGB(255, 54, 50, 48), 15 | modalSheetBackgroundColor: Color(0xffF2F2F2), 16 | onAccent: Color(0xff261E18), 17 | ); 18 | 19 | @override 20 | String get name => "Mocha"; 21 | 22 | @override 23 | AnimeStreamTheme get theme => AnimeStreamTheme( 24 | accentColor: Color(0xff8C7972), 25 | backgroundColor: Color(0xff261E18), 26 | backgroundSubColor: Color(0xff59473C), 27 | textMainColor: Color(0xffF2F2F2), 28 | textSubColor: Color(0xFFBFB0AA), 29 | modalSheetBackgroundColor: Color(0xff261E18), 30 | onAccent: Color(0xffF2F2F2), 31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /lib/ui/theme/monochrome.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/ui/theme/types.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class Monochrome implements ThemeItem { 5 | @override 6 | int get id => 02; 7 | 8 | @override 9 | AnimeStreamTheme get lightVariant => AnimeStreamTheme( 10 | accentColor: Colors.black, 11 | backgroundColor: Colors.white, 12 | backgroundSubColor: const Color.fromARGB(255, 172, 172, 172), 13 | textMainColor: Colors.black, 14 | textSubColor: Colors.black, 15 | modalSheetBackgroundColor: Colors.white, 16 | onAccent: Colors.white, 17 | ); 18 | 19 | @override 20 | String get name => "Monochrome"; 21 | 22 | @override 23 | AnimeStreamTheme get theme => AnimeStreamTheme( 24 | accentColor: Colors.white, 25 | backgroundColor: Colors.black, 26 | backgroundSubColor: Color.fromARGB(255, 36, 36, 36), 27 | textMainColor: Colors.white, 28 | textSubColor: Color.fromARGB(255, 180, 180, 180), 29 | modalSheetBackgroundColor: Color(0xff121212), 30 | onAccent: Colors.black, 31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /lib/ui/theme/neonGreen.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/ui/theme/types.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class NeonGreen implements ThemeItem { 5 | @override 6 | int get id => 08; 7 | 8 | @override 9 | AnimeStreamTheme get lightVariant => AnimeStreamTheme( 10 | accentColor: Color(0xff00c896), 11 | backgroundColor: Color(0xfff5f9fc), 12 | modalSheetBackgroundColor: Color(0xffffffff), 13 | backgroundSubColor: Color(0xffe0eaf2), 14 | textMainColor: Color(0xff102a39), 15 | textSubColor: Color(0xff5d717f), 16 | onAccent: Colors.white, 17 | ); 18 | 19 | @override 20 | String get name => "Neon Green"; 21 | 22 | @override 23 | AnimeStreamTheme get theme => AnimeStreamTheme( 24 | accentColor: Color(0xff27e9b5), 25 | backgroundColor: Color(0xff051824), 26 | modalSheetBackgroundColor: Color(0xff162936), 27 | backgroundSubColor: Color(0xff2a3e4d), 28 | textMainColor: Color(0xffffffff), 29 | textSubColor: Color(0xffb0b8c1), 30 | onAccent: Colors.black, 31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /lib/ui/theme/sakura.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/ui/theme/types.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class Sakura implements ThemeItem { 5 | @override 6 | int get id => 07; 7 | 8 | @override 9 | AnimeStreamTheme get lightVariant => AnimeStreamTheme( 10 | accentColor: Color(0xFFF06292), 11 | backgroundColor: Color(0xFFFFF8F8), 12 | backgroundSubColor: Color(0xFFFCE4EC), 13 | textMainColor: Color(0xFF333333), 14 | textSubColor: Color(0xFF767676), 15 | modalSheetBackgroundColor: Color(0xFFFCECEF), 16 | onAccent: Color(0xFFFFFFFF), 17 | ); 18 | 19 | @override 20 | String get name => "Sakura"; 21 | 22 | @override 23 | AnimeStreamTheme get theme => AnimeStreamTheme( 24 | accentColor: Color(0xFFFF8FAB), 25 | backgroundColor: Color(0xFF1A1A1A), 26 | backgroundSubColor: Color(0xFF332A2D), 27 | textMainColor: Color(0xFFF8F8F8), 28 | textSubColor: Color(0xFFBBBBBB), 29 | modalSheetBackgroundColor: Color.fromARGB(255, 31, 31, 31), 30 | onAccent: Color(0xFF333333), 31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /lib/ui/theme/themes.dart: -------------------------------------------------------------------------------- 1 | import 'package:animestream/ui/theme/amethyst.dart'; 2 | import 'package:animestream/ui/theme/coldPurple.dart'; 3 | import 'package:animestream/ui/theme/hotPink.dart'; 4 | import 'package:animestream/ui/theme/lime.dart'; 5 | import 'package:animestream/ui/theme/mocha.dart'; 6 | import 'package:animestream/ui/theme/monochrome.dart'; 7 | import 'package:animestream/ui/theme/neonGreen.dart'; 8 | import 'package:animestream/ui/theme/sakura.dart'; 9 | import 'package:animestream/ui/theme/types.dart'; 10 | import 'package:flutter/material.dart'; 11 | 12 | /** List of available themes. 13 | * 14 | The theme list in UI screen is generated from this list */ 15 | List availableThemes = [ 16 | LimeZest(), // ids are in order 0 -> n 17 | Monochrome(), 18 | ColdPurple(), 19 | HotPink(), 20 | Amethyst(), 21 | Mocha(), 22 | Sakura(), 23 | NeonGreen(), 24 | ]; 25 | 26 | // Represents a generic light theme (used only for its values) 27 | AnimeStreamTheme lightModeValues = AnimeStreamTheme( 28 | textMainColor: Colors.black, 29 | textSubColor: Color.fromARGB(255, 61, 61, 61), 30 | backgroundColor: Colors.white, 31 | backgroundSubColor: Color.fromARGB(255, 179, 179, 179), 32 | modalSheetBackgroundColor: Colors.white, 33 | accentColor: Colors.black, // ignore this field 34 | onAccent: Colors.white 35 | ); 36 | 37 | // Represents a generic dark theme (used only for its values) 38 | AnimeStreamTheme darkModeValues = AnimeStreamTheme( 39 | backgroundColor: Color.fromARGB(255, 24, 24, 24), 40 | backgroundSubColor: const Color.fromARGB(255, 36, 36, 36), 41 | textMainColor: Colors.white, 42 | textSubColor: Color.fromARGB(255, 180, 180, 180), 43 | modalSheetBackgroundColor: Color(0xff121212), 44 | accentColor: Colors.black, // ignore this field 45 | onAccent: Colors.white 46 | ); 47 | -------------------------------------------------------------------------------- /lib/ui/theme/types.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class ThemeItem { 4 | final String name; // Theme's name 5 | final AnimeStreamTheme theme; // Dark variant of the theme 6 | final AnimeStreamTheme lightVariant; // Light variant of the theme 7 | final int id; // Theme ID 8 | 9 | ThemeItem({ 10 | required this.id, 11 | required this.name, 12 | required this.theme, 13 | required this.lightVariant, 14 | }); 15 | } 16 | 17 | class AnimeStreamTheme { 18 | //core theme 19 | Color backgroundColor; //background 20 | Color accentColor; //accent 21 | Color textMainColor; //for main texts 22 | Color textSubColor; //for description|sub texts 23 | Color backgroundSubColor; //for card tints and some button highlights 24 | Color modalSheetBackgroundColor; //for modal sheet (no issue being same as background) 25 | Color onAccent; 26 | 27 | AnimeStreamTheme({ 28 | required this.accentColor, 29 | required this.backgroundColor, 30 | required this.backgroundSubColor, 31 | required this.textMainColor, 32 | required this.textSubColor, 33 | required this.modalSheetBackgroundColor, 34 | required this.onAccent, 35 | }); 36 | } -------------------------------------------------------------------------------- /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 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | void fl_register_plugins(FlPluginRegistry* registry) { 21 | g_autoptr(FlPluginRegistrar) awesome_notifications_registrar = 22 | fl_plugin_registry_get_registrar_for_plugin(registry, "AwesomeNotificationsPlugin"); 23 | awesome_notifications_plugin_register_with_registrar(awesome_notifications_registrar); 24 | g_autoptr(FlPluginRegistrar) desktop_webview_window_registrar = 25 | fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopWebviewWindowPlugin"); 26 | desktop_webview_window_plugin_register_with_registrar(desktop_webview_window_registrar); 27 | g_autoptr(FlPluginRegistrar) dynamic_color_registrar = 28 | fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin"); 29 | dynamic_color_plugin_register_with_registrar(dynamic_color_registrar); 30 | g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = 31 | fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); 32 | flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); 33 | g_autoptr(FlPluginRegistrar) gtk_registrar = 34 | fl_plugin_registry_get_registrar_for_plugin(registry, "GtkPlugin"); 35 | gtk_plugin_register_with_registrar(gtk_registrar); 36 | g_autoptr(FlPluginRegistrar) open_file_linux_registrar = 37 | fl_plugin_registry_get_registrar_for_plugin(registry, "OpenFileLinuxPlugin"); 38 | open_file_linux_plugin_register_with_registrar(open_file_linux_registrar); 39 | g_autoptr(FlPluginRegistrar) screen_retriever_linux_registrar = 40 | fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverLinuxPlugin"); 41 | screen_retriever_linux_plugin_register_with_registrar(screen_retriever_linux_registrar); 42 | g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = 43 | fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); 44 | url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); 45 | g_autoptr(FlPluginRegistrar) window_manager_registrar = 46 | fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin"); 47 | window_manager_plugin_register_with_registrar(window_manager_registrar); 48 | g_autoptr(FlPluginRegistrar) window_to_front_registrar = 49 | fl_plugin_registry_get_registrar_for_plugin(registry, "WindowToFrontPlugin"); 50 | window_to_front_plugin_register_with_registrar(window_to_front_registrar); 51 | } 52 | -------------------------------------------------------------------------------- /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 | awesome_notifications 7 | desktop_webview_window 8 | dynamic_color 9 | flutter_secure_storage_linux 10 | gtk 11 | open_file_linux 12 | screen_retriever_linux 13 | url_launcher_linux 14 | window_manager 15 | window_to_front 16 | ) 17 | 18 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 19 | ) 20 | 21 | set(PLUGIN_BUNDLED_LIBRARIES) 22 | 23 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 24 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) 25 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 26 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 27 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 28 | endforeach(plugin) 29 | 30 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 31 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) 32 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 33 | endforeach(ffi_plugin) 34 | -------------------------------------------------------------------------------- /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 "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | import app_links 9 | import awesome_notifications 10 | import desktop_webview_window 11 | import device_info_plus 12 | import dynamic_color 13 | import file_picker 14 | import flutter_secure_storage_macos 15 | import flutter_web_auth_2 16 | import open_file_mac 17 | import package_info_plus 18 | import path_provider_foundation 19 | import screen_retriever_macos 20 | import sqflite_darwin 21 | import url_launcher_macos 22 | import wakelock_plus 23 | import window_manager 24 | import window_to_front 25 | 26 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 27 | AppLinksMacosPlugin.register(with: registry.registrar(forPlugin: "AppLinksMacosPlugin")) 28 | AwesomeNotificationsPlugin.register(with: registry.registrar(forPlugin: "AwesomeNotificationsPlugin")) 29 | DesktopWebviewWindowPlugin.register(with: registry.registrar(forPlugin: "DesktopWebviewWindowPlugin")) 30 | DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) 31 | DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin")) 32 | FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin")) 33 | FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) 34 | FlutterWebAuth2Plugin.register(with: registry.registrar(forPlugin: "FlutterWebAuth2Plugin")) 35 | OpenFilePlugin.register(with: registry.registrar(forPlugin: "OpenFilePlugin")) 36 | FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) 37 | PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) 38 | ScreenRetrieverMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverMacosPlugin")) 39 | SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) 40 | UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) 41 | WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin")) 42 | WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin")) 43 | WindowToFrontPlugin.register(with: registry.registrar(forPlugin: "WindowToFrontPlugin")) 44 | } 45 | -------------------------------------------------------------------------------- /macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /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 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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 = animestream 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.animestream 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2023 com.example. All rights reserved. 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 | 12 | 13 | -------------------------------------------------------------------------------- /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 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import FlutterMacOS 2 | import Cocoa 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 | -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility in the flutter_test package. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:animestream/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(const AnimeStream()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/web/favicon.png -------------------------------------------------------------------------------- /web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/web/icons/Icon-192.png -------------------------------------------------------------------------------- /web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/web/icons/Icon-512.png -------------------------------------------------------------------------------- /web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "animestream", 3 | "short_name": "animestream", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /web/splash/img/dark-1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/web/splash/img/dark-1x.png -------------------------------------------------------------------------------- /web/splash/img/dark-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/web/splash/img/dark-2x.png -------------------------------------------------------------------------------- /web/splash/img/dark-3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/web/splash/img/dark-3x.png -------------------------------------------------------------------------------- /web/splash/img/dark-4x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/web/splash/img/dark-4x.png -------------------------------------------------------------------------------- /web/splash/img/light-1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/web/splash/img/light-1x.png -------------------------------------------------------------------------------- /web/splash/img/light-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/web/splash/img/light-2x.png -------------------------------------------------------------------------------- /web/splash/img/light-3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/web/splash/img/light-3x.png -------------------------------------------------------------------------------- /web/splash/img/light-4x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/web/splash/img/light-4x.png -------------------------------------------------------------------------------- /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 | #include 18 | #include 19 | #include 20 | 21 | void RegisterPlugins(flutter::PluginRegistry* registry) { 22 | AppLinksPluginCApiRegisterWithRegistrar( 23 | registry->GetRegistrarForPlugin("AppLinksPluginCApi")); 24 | AwesomeNotificationsPluginCApiRegisterWithRegistrar( 25 | registry->GetRegistrarForPlugin("AwesomeNotificationsPluginCApi")); 26 | DesktopWebviewWindowPluginRegisterWithRegistrar( 27 | registry->GetRegistrarForPlugin("DesktopWebviewWindowPlugin")); 28 | DynamicColorPluginCApiRegisterWithRegistrar( 29 | registry->GetRegistrarForPlugin("DynamicColorPluginCApi")); 30 | FlutterSecureStorageWindowsPluginRegisterWithRegistrar( 31 | registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); 32 | PermissionHandlerWindowsPluginRegisterWithRegistrar( 33 | registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); 34 | ScreenRetrieverWindowsPluginCApiRegisterWithRegistrar( 35 | registry->GetRegistrarForPlugin("ScreenRetrieverWindowsPluginCApi")); 36 | UrlLauncherWindowsRegisterWithRegistrar( 37 | registry->GetRegistrarForPlugin("UrlLauncherWindows")); 38 | VideoPlayerWinPluginCApiRegisterWithRegistrar( 39 | registry->GetRegistrarForPlugin("VideoPlayerWinPluginCApi")); 40 | WindowManagerPluginRegisterWithRegistrar( 41 | registry->GetRegistrarForPlugin("WindowManagerPlugin")); 42 | WindowToFrontPluginRegisterWithRegistrar( 43 | registry->GetRegistrarForPlugin("WindowToFrontPlugin")); 44 | } 45 | -------------------------------------------------------------------------------- /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 | app_links 7 | awesome_notifications 8 | desktop_webview_window 9 | dynamic_color 10 | flutter_secure_storage_windows 11 | permission_handler_windows 12 | screen_retriever_windows 13 | url_launcher_windows 14 | video_player_win 15 | window_manager 16 | window_to_front 17 | ) 18 | 19 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 20 | ) 21 | 22 | set(PLUGIN_BUNDLED_LIBRARIES) 23 | 24 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 25 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) 26 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 27 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 28 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 29 | endforeach(plugin) 30 | 31 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 32 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) 33 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 34 | endforeach(ffi_plugin) 35 | -------------------------------------------------------------------------------- /windows/runner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | project(runner LANGUAGES CXX) 3 | 4 | # Define the application target. To change its name, change BINARY_NAME in the 5 | # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer 6 | # work. 7 | # 8 | # Any new source files that you add to the application should be added here. 9 | add_executable(${BINARY_NAME} WIN32 10 | "flutter_window.cpp" 11 | "main.cpp" 12 | "utils.cpp" 13 | "win32_window.cpp" 14 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 15 | "Runner.rc" 16 | "runner.exe.manifest" 17 | ) 18 | 19 | # Apply the standard set of build settings. This can be removed for applications 20 | # that need different build settings. 21 | apply_standard_settings(${BINARY_NAME}) 22 | 23 | # Add preprocessor definitions for the build version. 24 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") 25 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") 26 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") 27 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") 28 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") 29 | 30 | # Disable Windows macros that collide with C++ standard library functions. 31 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") 32 | 33 | # Add dependency libraries and include directories. Add any application-specific 34 | # dependencies here. 35 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) 36 | target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") 37 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") 38 | 39 | # Run the Flutter tool portions of the build. This must not be removed. 40 | add_dependencies(${BINARY_NAME} flutter_assemble) 41 | -------------------------------------------------------------------------------- /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 | #if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) 64 | #define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD 65 | #else 66 | #define VERSION_AS_NUMBER 1,0,0,0 67 | #endif 68 | 69 | #if defined(FLUTTER_VERSION) 70 | #define VERSION_AS_STRING FLUTTER_VERSION 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", "com.example" "\0" 93 | VALUE "FileDescription", "animestream" "\0" 94 | VALUE "FileVersion", VERSION_AS_STRING "\0" 95 | VALUE "InternalName", "animestream" "\0" 96 | VALUE "LegalCopyright", "Copyright (C) 2023 com.example. All rights reserved." "\0" 97 | VALUE "OriginalFilename", "animestream.exe" "\0" 98 | VALUE "ProductName", "animestream" "\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 | 30 | flutter_controller_->engine()->SetNextFrameCallback([&]() { 31 | this->Show(); 32 | }); 33 | 34 | // Flutter can complete the first frame before the "show window" callback is 35 | // registered. The following call ensures a frame is pending to ensure the 36 | // window is shown. It is a no-op if the first frame hasn't completed yet. 37 | flutter_controller_->ForceRedraw(); 38 | 39 | return true; 40 | } 41 | 42 | void FlutterWindow::OnDestroy() { 43 | if (flutter_controller_) { 44 | flutter_controller_ = nullptr; 45 | } 46 | 47 | Win32Window::OnDestroy(); 48 | } 49 | 50 | LRESULT 51 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message, 52 | WPARAM const wparam, 53 | LPARAM const lparam) noexcept { 54 | // Give Flutter, including plugins, an opportunity to handle window messages. 55 | if (flutter_controller_) { 56 | std::optional result = 57 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, 58 | lparam); 59 | if (result) { 60 | return *result; 61 | } 62 | } 63 | 64 | switch (message) { 65 | case WM_FONTCHANGE: 66 | flutter_controller_->engine()->ReloadSystemFonts(); 67 | break; 68 | } 69 | 70 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam); 71 | } 72 | -------------------------------------------------------------------------------- /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 | 5 | #include "flutter_window.h" 6 | #include "utils.h" 7 | 8 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, 9 | _In_ wchar_t *command_line, _In_ int show_command) { 10 | // Attach to console when present (e.g., 'flutter run') or create a 11 | // new console when running with a debugger. 12 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { 13 | CreateAndAttachConsole(); 14 | } 15 | 16 | // Initialize COM, so that it is available for use in the library and/or 17 | // plugins. 18 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); 19 | 20 | flutter::DartProject project(L"data"); 21 | 22 | std::vector command_line_arguments = 23 | GetCommandLineArguments(); 24 | 25 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); 26 | 27 | FlutterWindow window(project); 28 | Win32Window::Point origin(10, 10); 29 | Win32Window::Size size(1280, 720); 30 | if (!window.Create(L"animestream", origin, size)) { 31 | return EXIT_FAILURE; 32 | } 33 | window.SetQuitOnClose(true); 34 | 35 | ::MSG msg; 36 | while (::GetMessage(&msg, nullptr, 0, 0)) { 37 | ::TranslateMessage(&msg); 38 | ::DispatchMessage(&msg); 39 | } 40 | 41 | ::CoUninitialize(); 42 | return EXIT_SUCCESS; 43 | } 44 | -------------------------------------------------------------------------------- /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/frostnova721/animestream/e8cef5a4ad576728bf02290e1cce83eed00fd09a/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 | -1; // remove the trailing null character 52 | int input_length = (int)wcslen(utf16_string); 53 | std::string utf8_string; 54 | if (target_length <= 0 || target_length > utf8_string.max_size()) { 55 | return utf8_string; 56 | } 57 | utf8_string.resize(target_length); 58 | int converted_length = ::WideCharToMultiByte( 59 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 60 | input_length, utf8_string.data(), target_length, nullptr, nullptr); 61 | if (converted_length == 0) { 62 | return std::string(); 63 | } 64 | return utf8_string; 65 | } 66 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------