├── .fvm
├── flutter_sdk
└── fvm_config.json
├── .gitignore
├── .metadata
├── LICENSE
├── README.md
├── analysis_options.yaml
├── android
├── .gitignore
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── github
│ │ │ │ └── alist
│ │ │ │ ├── App.kt
│ │ │ │ ├── DownloadingNotificationService.kt
│ │ │ │ ├── activity
│ │ │ │ ├── MainActivity.kt
│ │ │ │ └── PlayerActivity.kt
│ │ │ │ ├── bean
│ │ │ │ ├── ExternalPlayer.kt
│ │ │ │ ├── FindVideoRecordResp.kt
│ │ │ │ └── VideoItem.kt
│ │ │ │ ├── fileprovider
│ │ │ │ └── AListFileProvider.kt
│ │ │ │ ├── plugin
│ │ │ │ └── AlistPlugin.kt
│ │ │ │ ├── utils
│ │ │ │ ├── FileProviderUtils.java
│ │ │ │ ├── FlutterMethods.kt
│ │ │ │ ├── GsonUtils.kt
│ │ │ │ └── PackageManagerUtils.kt
│ │ │ │ └── widget
│ │ │ │ └── AlistClientVideoPlayer.java
│ │ └── res
│ │ │ ├── drawable-xxhdpi
│ │ │ └── ic_ffwd.png
│ │ │ ├── drawable
│ │ │ └── launch_background.xml
│ │ │ ├── layout
│ │ │ ├── activity_player.xml
│ │ │ └── video_layout_alist_client.xml
│ │ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_splash_android.png
│ │ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_splash_android.png
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_splash_android.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_splash_android.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_splash_android.png
│ │ │ ├── values-night
│ │ │ └── styles.xml
│ │ │ ├── values-zh
│ │ │ └── strings.xml
│ │ │ ├── values
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ │ └── xml
│ │ │ └── alist_file_paths.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── assets
└── images
│ ├── 2.0x
│ ├── account_icon.png
│ ├── account_icon_choosed.png
│ ├── file_type_apk.png
│ ├── file_type_audio.png
│ ├── file_type_code.png
│ ├── file_type_docment.png
│ ├── file_type_excel.png
│ ├── file_type_folder.png
│ ├── file_type_image.png
│ ├── file_type_md.png
│ ├── file_type_pdf.png
│ ├── file_type_ppt.png
│ ├── file_type_unknow.png
│ ├── file_type_video.png
│ ├── file_type_word.png
│ ├── file_type_zip.png
│ ├── icon_arrow_right.png
│ ├── icon_ffwd.png
│ ├── login_screen_account.png
│ ├── login_screen_password.png
│ ├── login_screen_server_url.png
│ ├── logo.png
│ ├── settings_screen_about.png
│ ├── settings_screen_account.png
│ ├── settings_screen_cache_manager.png
│ ├── settings_screen_donate.png
│ ├── settings_screen_download.png
│ ├── settings_screen_player.png
│ └── settings_screen_privacy_policy.png
│ ├── 3.0x
│ ├── account_icon.png
│ ├── account_icon_choosed.png
│ ├── file_type_apk.png
│ ├── file_type_audio.png
│ ├── file_type_code.png
│ ├── file_type_docment.png
│ ├── file_type_excel.png
│ ├── file_type_folder.png
│ ├── file_type_image.png
│ ├── file_type_md.png
│ ├── file_type_pdf.png
│ ├── file_type_ppt.png
│ ├── file_type_unknow.png
│ ├── file_type_video.png
│ ├── file_type_word.png
│ ├── file_type_zip.png
│ ├── icon_arrow_right.png
│ ├── icon_ffwd.png
│ ├── login_screen_account.png
│ ├── login_screen_password.png
│ ├── login_screen_server_url.png
│ ├── logo.png
│ ├── settings_screen_about.png
│ ├── settings_screen_account.png
│ ├── settings_screen_cache_manager.png
│ ├── settings_screen_donate.png
│ ├── settings_screen_download.png
│ ├── settings_screen_player.png
│ └── settings_screen_privacy_policy.png
│ ├── account_icon.png
│ ├── account_icon_choosed.png
│ ├── file_type_apk.png
│ ├── file_type_audio.png
│ ├── file_type_code.png
│ ├── file_type_docment.png
│ ├── file_type_excel.png
│ ├── file_type_folder.png
│ ├── file_type_image.png
│ ├── file_type_md.png
│ ├── file_type_pdf.png
│ ├── file_type_ppt.png
│ ├── file_type_unknow.png
│ ├── file_type_video.png
│ ├── file_type_word.png
│ ├── file_type_zip.png
│ ├── ic_infuse.png
│ ├── ic_launcher.png
│ ├── ic_nplayer.png
│ ├── ic_vlc.png
│ ├── icon_arrow_right.png
│ ├── icon_ffwd.png
│ ├── login_screen_account.png
│ ├── login_screen_password.png
│ ├── login_screen_server_url.png
│ ├── logo.png
│ ├── settings_screen_about.png
│ ├── settings_screen_account.png
│ ├── settings_screen_cache_manager.png
│ ├── settings_screen_donate.png
│ ├── settings_screen_download.png
│ ├── settings_screen_player.png
│ └── settings_screen_privacy_policy.png
├── generateKeys
├── github
├── android_github.png
├── appstore.png
└── banner.jpg
├── ios
├── .gitignore
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Podfile
├── Podfile.lock
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
└── Runner
│ ├── AppDelegate.swift
│ ├── AppSupportFiles
│ └── license.crt
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-App-20x20@1x.png
│ │ ├── Icon-App-20x20@2x.png
│ │ ├── Icon-App-20x20@3x.png
│ │ ├── Icon-App-29x29@1x.png
│ │ ├── Icon-App-29x29@2x.png
│ │ ├── Icon-App-29x29@3x.png
│ │ ├── Icon-App-40x40@1x.png
│ │ ├── Icon-App-40x40@2x.png
│ │ ├── Icon-App-40x40@3x.png
│ │ ├── Icon-App-60x60@2x.png
│ │ ├── Icon-App-60x60@3x.png
│ │ ├── Icon-App-76x76@1x.png
│ │ ├── Icon-App-76x76@2x.png
│ │ ├── Icon-App-83.5x83.5@2x.png
│ │ └── Icon-App-iTunes.png
│ ├── Contents.json
│ └── LaunchImage.imageset
│ │ ├── Contents.json
│ │ ├── README.md
│ │ ├── ic_splash_ios.png
│ │ ├── ic_splash_ios@2x.png
│ │ └── ic_splash_ios@3x.png
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ ├── Runner-Bridging-Header.h
│ ├── Runner.entitlements
│ ├── en.lproj
│ └── InfoPlist.strings
│ └── zh-Hans.lproj
│ ├── InfoPlist.strings
│ ├── LaunchScreen.strings
│ └── Main.strings
├── lib
├── database
│ ├── alist_database.dart
│ ├── alist_database.g.dart
│ ├── alist_database_controller.dart
│ ├── dao
│ │ ├── favorite_dao.dart
│ │ ├── file_download_record_dao.dart
│ │ ├── file_password_dao.dart
│ │ ├── file_viewing_record_dao.dart
│ │ ├── server_dao.dart
│ │ └── video_viewing_record_dao.dart
│ └── table
│ │ ├── favorite.dart
│ │ ├── file_download_record.dart
│ │ ├── file_password.dart
│ │ ├── file_viewing_record.dart
│ │ ├── server.dart
│ │ └── video_viewing_record.dart
├── entity
│ ├── app_version_resp.dart
│ ├── copy_move_req.dart
│ ├── donate_config_entity.dart
│ ├── downloads_info.dart
│ ├── file_info_resp_entity.dart
│ ├── file_list_resp_entity.dart
│ ├── file_remove_req.dart
│ ├── file_rename_req.dart
│ ├── file_search_resp.dart
│ ├── http_result.dart
│ ├── login_resp_entity.dart
│ ├── mkdir_req.dart
│ ├── my_info_resp.dart
│ ├── player_resolve_info_entity.dart
│ └── public_settings_resp.dart
├── generated
│ ├── color_schemes.g.dart
│ ├── images.dart
│ └── json
│ │ ├── app_version_resp.g.dart
│ │ ├── base
│ │ ├── json_convert_content.dart
│ │ └── json_field.dart
│ │ ├── copy_move_req.g.dart
│ │ ├── donate_config_entity.g.dart
│ │ ├── downloads_info.g.dart
│ │ ├── file_info_resp_entity.g.dart
│ │ ├── file_list_resp_entity.g.dart
│ │ ├── file_remove_req.g.dart
│ │ ├── file_rename_req.g.dart
│ │ ├── file_search_resp.g.dart
│ │ ├── login_resp_entity.g.dart
│ │ ├── mkdir_req.g.dart
│ │ ├── my_info_resp.g.dart
│ │ ├── player_resolve_info_entity.g.dart
│ │ └── public_settings_resp.g.dart
├── l10n
│ ├── alist_translations.dart
│ ├── intl_en_us.dart
│ ├── intl_keys.dart
│ └── intl_zh_cn.dart
├── main.dart
├── net
│ ├── base_entity.dart
│ ├── dio_utils.dart
│ ├── intercept.dart
│ ├── json_parse_error.dart
│ ├── net.dart
│ ├── net_error_handler.dart
│ └── redirect_exception.dart
├── router.dart
├── screen
│ ├── aboute_screen.dart
│ ├── account_screen.dart
│ ├── audio_player_screen.dart
│ ├── cache_manager.dart
│ ├── donate_screen.dart
│ ├── download_manager_screen.dart
│ ├── favorite_screen.dart
│ ├── file_list
│ │ ├── director_password_dialog.dart
│ │ ├── file_copy_move_dialog.dart
│ │ ├── file_list_menu_anchor.dart
│ │ ├── file_list_navigator.dart
│ │ ├── file_list_screen.dart
│ │ ├── file_rename_dialog.dart
│ │ └── mkdir_dialog.dart
│ ├── file_reader_screen.dart
│ ├── file_search_screen.dart
│ ├── gallery_screen.dart
│ ├── home_screen.dart
│ ├── login_screen.dart
│ ├── pdf_reader_screen.dart
│ ├── player_settings_screen.dart
│ ├── recents_screen.dart
│ ├── settings_screen.dart
│ ├── splash_screen.dart
│ ├── uploading_files_screen.dart
│ ├── video_player_screen.dart
│ └── web_screen.dart
├── util
│ ├── alist_plugin.dart
│ ├── constant.dart
│ ├── download
│ │ ├── download_http_client.dart
│ │ ├── download_manager.dart
│ │ ├── download_task.dart
│ │ └── download_task_status.dart
│ ├── file_password_helper.dart
│ ├── file_type.dart
│ ├── file_utils.dart
│ ├── focus_node_utils.dart
│ ├── global.dart
│ ├── iterator.dart
│ ├── keyboard_utils.dart
│ ├── lock_caching_audio_source.dart
│ ├── log_utils.dart
│ ├── markdown_utils.dart
│ ├── method_call_handler.dart
│ ├── named_router.dart
│ ├── nature_sort.dart
│ ├── proxy.dart
│ ├── string_utils.dart
│ ├── user_controller.dart
│ ├── video_player_util.dart
│ └── widget_utils.dart
└── widget
│ ├── alist_checkbox.dart
│ ├── alist_scaffold.dart
│ ├── alist_will_pop_scope.dart
│ ├── bottom_navigation_bar.dart
│ ├── config_file_name_max_lines_dialog.dart
│ ├── file_details_dialog.dart
│ ├── file_list_item_view.dart
│ ├── loading_status_widget.dart
│ ├── overflow_text.dart
│ ├── player_selector_dialog.dart
│ ├── player_skin.dart
│ ├── slider.dart
│ └── update_dialog.dart
├── linux
├── .gitignore
├── CMakeLists.txt
├── flutter
│ ├── CMakeLists.txt
│ ├── generated_plugin_registrant.cc
│ ├── generated_plugin_registrant.h
│ └── generated_plugins.cmake
├── main.cc
├── my_application.cc
└── my_application.h
├── macos
├── .gitignore
├── Flutter
│ ├── Flutter-Debug.xcconfig
│ ├── Flutter-Release.xcconfig
│ └── GeneratedPluginRegistrant.swift
├── Podfile
├── Podfile.lock
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── app_icon_1024.png
│ │ ├── app_icon_128.png
│ │ ├── app_icon_16.png
│ │ ├── app_icon_256.png
│ │ ├── app_icon_32.png
│ │ ├── app_icon_512.png
│ │ └── app_icon_64.png
│ ├── Base.lproj
│ └── MainMenu.xib
│ ├── Configs
│ ├── AppInfo.xcconfig
│ ├── Debug.xcconfig
│ ├── Release.xcconfig
│ └── Warnings.xcconfig
│ ├── DebugProfile.entitlements
│ ├── Info.plist
│ ├── MainFlutterWindow.swift
│ └── Release.entitlements
├── pubspec.lock
├── pubspec.yaml
├── test
└── widget_test.dart
├── web
├── favicon.png
├── icons
│ ├── Icon-192.png
│ ├── Icon-512.png
│ ├── Icon-maskable-192.png
│ └── Icon-maskable-512.png
├── index.html
└── manifest.json
└── windows
├── .gitignore
├── CMakeLists.txt
├── flutter
├── CMakeLists.txt
├── generated_plugin_registrant.cc
├── generated_plugin_registrant.h
└── generated_plugins.cmake
└── runner
├── CMakeLists.txt
├── Runner.rc
├── flutter_window.cpp
├── flutter_window.h
├── main.cpp
├── resource.h
├── resources
└── app_icon.ico
├── runner.exe.manifest
├── utils.cpp
├── utils.h
├── win32_window.cpp
└── win32_window.h
/.fvm/flutter_sdk:
--------------------------------------------------------------------------------
1 | /Users/tangrui/.fvm/versions/3.13.8
--------------------------------------------------------------------------------
/.fvm/fvm_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "flutterSdkVersion": "3.13.8",
3 | "flavors": {}
4 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .build/
9 | .buildlog/
10 | .history
11 | .svn/
12 | .swiftpm/
13 | migrate_working_dir/
14 |
15 | # IntelliJ related
16 | *.iml
17 | *.ipr
18 | *.iws
19 | .idea/
20 |
21 | # The .vscode folder contains launch configuration and tasks you configure in
22 | # VS Code which you may wish to be included in version control, so this line
23 | # is commented out by default.
24 | #.vscode/
25 |
26 | # Flutter/Dart/Pub related
27 | **/doc/api/
28 | **/ios/Flutter/.last_build_id
29 | .dart_tool/
30 | .flutter-plugins
31 | .flutter-plugins-dependencies
32 | .packages
33 | .pub-cache/
34 | .pub/
35 | /build/
36 |
37 | # Symbolication related
38 | app.*.symbols
39 |
40 | # Obfuscation related
41 | app.*.map.json
42 |
43 | # Android Studio will place build artifacts here
44 | /android/app/debug
45 | /android/app/profile
46 | /android/app/release
47 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled.
5 |
6 | version:
7 | revision: f72efea43c3013323d1b95cff571f3c1caa37583
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: f72efea43c3013323d1b95cff571f3c1caa37583
17 | base_revision: f72efea43c3013323d1b95cff571f3c1caa37583
18 | - platform: android
19 | create_revision: f72efea43c3013323d1b95cff571f3c1caa37583
20 | base_revision: f72efea43c3013323d1b95cff571f3c1caa37583
21 | - platform: ios
22 | create_revision: f72efea43c3013323d1b95cff571f3c1caa37583
23 | base_revision: f72efea43c3013323d1b95cff571f3c1caa37583
24 | - platform: linux
25 | create_revision: f72efea43c3013323d1b95cff571f3c1caa37583
26 | base_revision: f72efea43c3013323d1b95cff571f3c1caa37583
27 | - platform: macos
28 | create_revision: f72efea43c3013323d1b95cff571f3c1caa37583
29 | base_revision: f72efea43c3013323d1b95cff571f3c1caa37583
30 | - platform: web
31 | create_revision: f72efea43c3013323d1b95cff571f3c1caa37583
32 | base_revision: f72efea43c3013323d1b95cff571f3c1caa37583
33 | - platform: windows
34 | create_revision: f72efea43c3013323d1b95cff571f3c1caa37583
35 | base_revision: f72efea43c3013323d1b95cff571f3c1caa37583
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ALClient
2 |
3 | 
4 |
5 | ## AppStore
6 | 
7 |
8 | ## Android(蓝奏云下载)
9 | https://wwxv.lanzoul.com/b002uv0t2b
10 | 密码:alist
11 |
12 | ## Android
13 | 
14 |
15 | ALClient is a mobile application developed using Flutter based on [the AList project](https://github.com/alist-org/alist), supporting both Android and IOS platforms. It provides various functions, including online browsing of files, online viewing of videos, audios, and browsing of documents in the AList project. It also supports file uploading (to be developed) and file management (to be developed). Users can easily access and watch various types of media files in the AList project through ALClient.
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | # This file configures the analyzer, which statically analyzes Dart code to
2 | # check for errors, warnings, and lints.
3 | #
4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled
5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
6 | # invoked from the command line by running `flutter analyze`.
7 |
8 | # The following line activates a set of recommended lints for Flutter apps,
9 | # packages, and plugins designed to encourage good coding practices.
10 | include: package:flutter_lints/flutter.yaml
11 |
12 | linter:
13 | # The lint rules applied to this project can be customized in the
14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml`
15 | # included above or to enable additional rules. A list of all available lints
16 | # and their documentation is published at
17 | # https://dart-lang.github.io/linter/lints/index.html.
18 | #
19 | # Instead of disabling a lint rule for the entire project in the
20 | # section below, it can also be suppressed for a single line of code
21 | # or a specific dart file by using the `// ignore: name_of_lint` and
22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file
23 | # producing the lint.
24 | rules:
25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule
26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
27 |
28 | # Additional information about this file can be found at
29 | # https://dart.dev/guides/language/analysis-options
30 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 | privacy.gradle
15 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
8 |
9 |
10 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
25 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/github/alist/App.kt:
--------------------------------------------------------------------------------
1 | package com.github.alist
2 |
3 | import android.content.Context
4 | import androidx.multidex.MultiDex
5 | import com.shuyu.gsyvideoplayer.GSYVideoManager
6 | import com.shuyu.gsyvideoplayer.model.VideoOptionModel
7 | import io.flutter.app.FlutterApplication
8 | import tv.danmaku.ijk.media.player.IjkMediaPlayer
9 |
10 |
11 | class App : FlutterApplication() {
12 | override fun onCreate() {
13 | super.onCreate()
14 |
15 | val gsyOptionModelList = mutableListOf()
16 | // 丢帧解决音视频不同步的文
17 | val videoOptionMode01 = VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1)
18 | val videoOptionMode02 =
19 | VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 0)
20 |
21 | // url切换400/404(http与https域名共用等)
22 | val videoOptionMode03 =
23 | VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_clear", 1)
24 | val videoOptionMode04 =
25 | VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_timeout", -1)
26 | gsyOptionModelList.add(videoOptionMode01)
27 | gsyOptionModelList.add(videoOptionMode02)
28 | gsyOptionModelList.add(videoOptionMode03)
29 | gsyOptionModelList.add(videoOptionMode04)
30 | GSYVideoManager.instance().optionModelList = gsyOptionModelList
31 | }
32 |
33 | override fun attachBaseContext(base: Context?) {
34 | super.attachBaseContext(base)
35 | MultiDex.install(this)
36 | }
37 | }
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/github/alist/DownloadingNotificationService.kt:
--------------------------------------------------------------------------------
1 | package com.github.alist
2 |
3 | import android.app.NotificationChannel
4 | import android.app.NotificationManager
5 | import android.app.Service
6 | import android.content.Context
7 | import android.content.Intent
8 | import android.os.Build
9 | import androidx.core.app.NotificationCompat
10 | import com.github.alist.client.R
11 |
12 | class DownloadingNotificationService : Service() {
13 | companion object {
14 | const val channelId = "com.github.alist.client.download"
15 | const val channelName = "Download"
16 | }
17 |
18 | override fun onBind(intent: Intent?) = null
19 |
20 | override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
21 | val notificationManager =
22 | getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
23 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
24 | val channel =
25 | NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH)
26 | notificationManager.createNotificationChannel(channel)
27 | }
28 | val notification = NotificationCompat.Builder(this, channelId)
29 | .setSmallIcon(R.mipmap.ic_launcher)
30 | .setContentTitle(getString(R.string.downloading_notification_title))
31 | .setContentText(getString(R.string.downloading_notification_content))
32 | .setAutoCancel(false)
33 | .setOngoing(true)
34 | .build()
35 | startForeground(1, notification)
36 | return super.onStartCommand(intent, flags, startId)
37 | }
38 | }
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/github/alist/activity/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.github.alist.activity
2 |
3 | import android.content.Intent
4 | import com.github.alist.plugin.AlistPlugin
5 | import com.ryanheise.audioservice.AudioServiceFragmentActivity
6 | import io.flutter.embedding.engine.FlutterEngine
7 | import kotlinx.coroutines.CoroutineScope
8 | import kotlinx.coroutines.MainScope
9 | import kotlinx.coroutines.cancel
10 |
11 | class MainActivity : AudioServiceFragmentActivity() {
12 | private val coroutineScope: CoroutineScope = MainScope()
13 | private val alistPlugin = AlistPlugin(this, coroutineScope)
14 |
15 | override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
16 | super.configureFlutterEngine(flutterEngine)
17 | flutterEngine.plugins.add(alistPlugin)
18 | }
19 |
20 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
21 | super.onActivityResult(requestCode, resultCode, data)
22 | alistPlugin.onActivityResult(requestCode, resultCode, data)
23 | }
24 |
25 | override fun onDestroy() {
26 | coroutineScope.cancel()
27 | super.onDestroy()
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/github/alist/bean/ExternalPlayer.kt:
--------------------------------------------------------------------------------
1 | package com.github.alist.bean
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | class ExternalPlayer(
6 | @SerializedName("packageName")
7 | val packageName: String,
8 | @SerializedName("activity")
9 | val activity: String,
10 | @SerializedName("label")
11 | val label: String,
12 | @SerializedName("icon")
13 | val icon: String
14 | )
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/github/alist/bean/FindVideoRecordResp.kt:
--------------------------------------------------------------------------------
1 | package com.github.alist.bean
2 |
3 | class FindVideoRecordResp(
4 | val videoCurrentPosition: Long?,
5 | val videoDuration: Long?
6 | )
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/github/alist/bean/VideoItem.kt:
--------------------------------------------------------------------------------
1 | package com.github.alist.bean
2 |
3 | class VideoItem(
4 | val name: String,
5 | val localPath: String?,
6 | val remotePath: String,
7 | val sign: String?,
8 | val provider: String?,
9 | val thumb: String?,
10 | val url: String,
11 | val modifiedMilliseconds: String?,
12 | val size: String?
13 | )
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/github/alist/fileprovider/AListFileProvider.kt:
--------------------------------------------------------------------------------
1 | package com.github.alist.fileprovider
2 |
3 | import androidx.core.content.FileProvider
4 |
5 | class AListFileProvider : FileProvider()
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/github/alist/utils/FileProviderUtils.java:
--------------------------------------------------------------------------------
1 | package com.github.alist.utils;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.net.Uri;
6 | import android.os.Build;
7 |
8 | import androidx.core.content.FileProvider;
9 |
10 | import java.io.File;
11 |
12 | public class FileProviderUtils {
13 | public static Uri getUriFromFile(Context context, File file) {
14 | Uri uri;
15 | if (Build.VERSION.SDK_INT >= 24) {
16 | uri = getUriForFile24(context, file);
17 | } else {
18 | uri = Uri.fromFile(file);
19 | }
20 | return uri;
21 | }
22 |
23 | public static Uri getUriForFile24(Context context, File file) {
24 | return FileProvider.getUriForFile(context,
25 | String.format("%s.alist_file_provider", context.getPackageName()), file);
26 | }
27 |
28 | public static void setIntentDataAndType(Context context,
29 | Intent intent,
30 | String type,
31 | File file,
32 | boolean writeAble) {
33 | if (Build.VERSION.SDK_INT >= 24) {
34 | intent.setDataAndType(getUriForFile24(context, file), type);
35 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
36 | if (writeAble) {
37 | intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
38 | }
39 | } else {
40 | intent.setDataAndType(Uri.fromFile(file), type);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/github/alist/utils/FlutterMethods.kt:
--------------------------------------------------------------------------------
1 | package com.github.alist.utils
2 |
3 | import com.github.alist.bean.FindVideoRecordResp
4 | import com.github.alist.bean.VideoItem
5 | import io.flutter.plugin.common.MethodChannel
6 |
7 | object FlutterMethods {
8 | lateinit var channel: MethodChannel
9 |
10 | fun findVideoRecordByPath(path: String, callback: (FindVideoRecordResp) -> Unit) {
11 | channel.invokeMethod(
12 | "findVideoRecordByPath",
13 | mutableMapOf("path" to path),
14 | object : MethodChannel.Result {
15 |
16 | override fun success(result: Any?) {
17 | if (result is String) {
18 | callback(GsonUtils.parseObject(result))
19 | }
20 | }
21 |
22 | override fun error(p0: String, p1: String?, p2: Any?) {
23 | }
24 |
25 | override fun notImplemented() {
26 | }
27 | })
28 | }
29 |
30 | fun deleteVideoRecord(path: String) {
31 | channel.invokeMethod(
32 | "deleteVideoRecord",
33 | mutableMapOf("path" to path)
34 | )
35 | }
36 |
37 | fun insertOrUpdateVideoRecord(
38 | path: String,
39 | videoCurrentPosition: Long,
40 | videoDuration: Long,
41 | sign: String?
42 | ) {
43 | channel.invokeMethod(
44 | "insertOrUpdateVideoRecord",
45 | mutableMapOf(
46 | "path" to path,
47 | "videoCurrentPosition" to videoCurrentPosition,
48 | "videoDuration" to videoDuration,
49 | "sign" to sign
50 | )
51 | )
52 | }
53 |
54 | fun onPayerDestroyed() {
55 | channel.invokeMethod("onPayerDestroyed", "")
56 | }
57 |
58 | fun addFileViewingRecord(video: VideoItem) {
59 | channel.invokeMethod(
60 | "addFileViewingRecord",
61 | mutableMapOf(
62 | "path" to video.remotePath,
63 | "name" to video.name,
64 | "sign" to video.sign,
65 | "size" to video.size,
66 | "thumb" to video.thumb,
67 | "modifiedMilliseconds" to video.modifiedMilliseconds,
68 | "provider" to video.provider
69 | )
70 | )
71 | }
72 | }
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/github/alist/utils/GsonUtils.kt:
--------------------------------------------------------------------------------
1 | package com.github.alist.utils
2 |
3 | import com.google.gson.Gson
4 | import com.google.gson.reflect.TypeToken
5 |
6 | object GsonUtils {
7 | val gson = Gson()
8 |
9 | inline fun parseMap(jsonText: String): Map {
10 | val resultType =
11 | TypeToken.getParameterized(MutableMap::class.java, K::class.java, V::class.java)
12 | return gson.fromJson(jsonText, resultType) as Map
13 | }
14 |
15 | inline fun parseList(jsonText: String): List {
16 | val resultType = TypeToken.getParameterized(List::class.java, T::class.java)
17 | return gson.fromJson(jsonText, resultType) as List
18 | }
19 |
20 | inline fun parseObject(jsonText: String): T {
21 | return gson.fromJson(jsonText, T::class.java)
22 | }
23 |
24 | fun toJsonString(jsonObj: Any): String {
25 | return gson.toJson(jsonObj)
26 | }
27 | }
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/github/alist/utils/PackageManagerUtils.kt:
--------------------------------------------------------------------------------
1 | package com.github.alist.utils
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.content.pm.PackageManager
6 | import android.graphics.Bitmap
7 | import android.net.Uri
8 | import android.os.Build
9 | import androidx.core.graphics.drawable.toBitmap
10 | import com.github.alist.bean.ExternalPlayer
11 | import kotlinx.coroutines.Dispatchers
12 | import kotlinx.coroutines.withContext
13 | import java.io.ByteArrayOutputStream
14 | import java.io.File
15 |
16 | object PackageManagerUtils {
17 | suspend fun loadExternalPlayerList(context: Context): List {
18 | return withContext(Dispatchers.IO) {
19 | val packageManager: PackageManager = context.packageManager
20 | val intent = Intent(Intent.ACTION_VIEW)
21 | intent.setDataAndType(Uri.parse("http://a.com/test.mp4"), "video/*")
22 | val resolveInfos = packageManager.queryIntentActivities(intent, 0)
23 |
24 | val resultList = mutableListOf()
25 | for (resolveInfo in resolveInfos) {
26 | val label = resolveInfo.activityInfo.loadLabel(packageManager)
27 |
28 | val file =
29 | File(context.cacheDir, "appIcon/${resolveInfo.activityInfo.packageName}.webp")
30 | if (!file.exists()) {
31 | file.parentFile?.mkdirs()
32 | val appIcon = resolveInfo.loadIcon(packageManager)
33 | val bitmap = appIcon.toBitmap()
34 | val byteArrayOutputStream = ByteArrayOutputStream()
35 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
36 | bitmap.compress(
37 | Bitmap.CompressFormat.WEBP_LOSSLESS,
38 | 100,
39 | byteArrayOutputStream
40 | )
41 | } else {
42 | bitmap.compress(Bitmap.CompressFormat.WEBP, 100, byteArrayOutputStream)
43 | }
44 | val byteArray = byteArrayOutputStream.toByteArray()
45 |
46 | val tmpFile = File("${file.absolutePath}.tmp")
47 | tmpFile.writeBytes(byteArray)
48 | tmpFile.renameTo(file)
49 | }
50 |
51 | resultList.add(
52 | ExternalPlayer(
53 | packageName = resolveInfo.activityInfo.packageName,
54 | activity = resolveInfo.activityInfo.name,
55 | label = label.toString(),
56 | icon = file.absolutePath
57 | )
58 | )
59 | }
60 | resultList
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-xxhdpi/ic_ffwd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/android/app/src/main/res/drawable-xxhdpi/ic_ffwd.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
9 |
10 |
11 |
12 |
13 | -
14 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/layout/activity_player.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_splash_android.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/android/app/src/main/res/mipmap-hdpi/ic_splash_android.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_splash_android.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/android/app/src/main/res/mipmap-mdpi/ic_splash_android.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_splash_android.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/android/app/src/main/res/mipmap-xhdpi/ic_splash_android.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_splash_android.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/android/app/src/main/res/mipmap-xxhdpi/ic_splash_android.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_splash_android.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/android/app/src/main/res/mipmap-xxxhdpi/ic_splash_android.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
17 |
22 |
23 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values-zh/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 文件下载中...
4 | 文件下载正在后台中...
5 | 倍速播放中
6 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Downloading...
4 | Files download is in the background.
5 | Playing at double speed
6 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
17 |
22 |
23 |
35 |
36 |
--------------------------------------------------------------------------------
/android/app/src/main/res/xml/alist_file_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
8 |
9 |
10 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
25 |
26 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.9.10'
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:7.2.0'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | mavenCentral()
18 | maven { url 'https://jitpack.io' }
19 | maven { url "https://maven.aliyun.com/repository/public" }
20 | }
21 | }
22 |
23 | rootProject.buildDir = '../build'
24 | subprojects {
25 | project.buildDir = "${rootProject.buildDir}/${project.name}"
26 | }
27 | subprojects {
28 | project.evaluationDependsOn(':app')
29 | }
30 |
31 | tasks.register("clean", Delete) {
32 | delete rootProject.buildDir
33 | }
34 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
6 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
4 | def properties = new Properties()
5 |
6 | assert localPropertiesFile.exists()
7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
8 |
9 | def flutterSdkPath = properties.getProperty("flutter.sdk")
10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
12 |
--------------------------------------------------------------------------------
/assets/images/2.0x/account_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/account_icon.png
--------------------------------------------------------------------------------
/assets/images/2.0x/account_icon_choosed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/account_icon_choosed.png
--------------------------------------------------------------------------------
/assets/images/2.0x/file_type_apk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/file_type_apk.png
--------------------------------------------------------------------------------
/assets/images/2.0x/file_type_audio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/file_type_audio.png
--------------------------------------------------------------------------------
/assets/images/2.0x/file_type_code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/file_type_code.png
--------------------------------------------------------------------------------
/assets/images/2.0x/file_type_docment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/file_type_docment.png
--------------------------------------------------------------------------------
/assets/images/2.0x/file_type_excel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/file_type_excel.png
--------------------------------------------------------------------------------
/assets/images/2.0x/file_type_folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/file_type_folder.png
--------------------------------------------------------------------------------
/assets/images/2.0x/file_type_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/file_type_image.png
--------------------------------------------------------------------------------
/assets/images/2.0x/file_type_md.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/file_type_md.png
--------------------------------------------------------------------------------
/assets/images/2.0x/file_type_pdf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/file_type_pdf.png
--------------------------------------------------------------------------------
/assets/images/2.0x/file_type_ppt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/file_type_ppt.png
--------------------------------------------------------------------------------
/assets/images/2.0x/file_type_unknow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/file_type_unknow.png
--------------------------------------------------------------------------------
/assets/images/2.0x/file_type_video.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/file_type_video.png
--------------------------------------------------------------------------------
/assets/images/2.0x/file_type_word.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/file_type_word.png
--------------------------------------------------------------------------------
/assets/images/2.0x/file_type_zip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/file_type_zip.png
--------------------------------------------------------------------------------
/assets/images/2.0x/icon_arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/icon_arrow_right.png
--------------------------------------------------------------------------------
/assets/images/2.0x/icon_ffwd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/icon_ffwd.png
--------------------------------------------------------------------------------
/assets/images/2.0x/login_screen_account.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/login_screen_account.png
--------------------------------------------------------------------------------
/assets/images/2.0x/login_screen_password.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/login_screen_password.png
--------------------------------------------------------------------------------
/assets/images/2.0x/login_screen_server_url.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/login_screen_server_url.png
--------------------------------------------------------------------------------
/assets/images/2.0x/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/logo.png
--------------------------------------------------------------------------------
/assets/images/2.0x/settings_screen_about.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/settings_screen_about.png
--------------------------------------------------------------------------------
/assets/images/2.0x/settings_screen_account.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/settings_screen_account.png
--------------------------------------------------------------------------------
/assets/images/2.0x/settings_screen_cache_manager.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/settings_screen_cache_manager.png
--------------------------------------------------------------------------------
/assets/images/2.0x/settings_screen_donate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/settings_screen_donate.png
--------------------------------------------------------------------------------
/assets/images/2.0x/settings_screen_download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/settings_screen_download.png
--------------------------------------------------------------------------------
/assets/images/2.0x/settings_screen_player.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/settings_screen_player.png
--------------------------------------------------------------------------------
/assets/images/2.0x/settings_screen_privacy_policy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/2.0x/settings_screen_privacy_policy.png
--------------------------------------------------------------------------------
/assets/images/3.0x/account_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/account_icon.png
--------------------------------------------------------------------------------
/assets/images/3.0x/account_icon_choosed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/account_icon_choosed.png
--------------------------------------------------------------------------------
/assets/images/3.0x/file_type_apk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/file_type_apk.png
--------------------------------------------------------------------------------
/assets/images/3.0x/file_type_audio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/file_type_audio.png
--------------------------------------------------------------------------------
/assets/images/3.0x/file_type_code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/file_type_code.png
--------------------------------------------------------------------------------
/assets/images/3.0x/file_type_docment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/file_type_docment.png
--------------------------------------------------------------------------------
/assets/images/3.0x/file_type_excel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/file_type_excel.png
--------------------------------------------------------------------------------
/assets/images/3.0x/file_type_folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/file_type_folder.png
--------------------------------------------------------------------------------
/assets/images/3.0x/file_type_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/file_type_image.png
--------------------------------------------------------------------------------
/assets/images/3.0x/file_type_md.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/file_type_md.png
--------------------------------------------------------------------------------
/assets/images/3.0x/file_type_pdf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/file_type_pdf.png
--------------------------------------------------------------------------------
/assets/images/3.0x/file_type_ppt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/file_type_ppt.png
--------------------------------------------------------------------------------
/assets/images/3.0x/file_type_unknow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/file_type_unknow.png
--------------------------------------------------------------------------------
/assets/images/3.0x/file_type_video.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/file_type_video.png
--------------------------------------------------------------------------------
/assets/images/3.0x/file_type_word.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/file_type_word.png
--------------------------------------------------------------------------------
/assets/images/3.0x/file_type_zip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/file_type_zip.png
--------------------------------------------------------------------------------
/assets/images/3.0x/icon_arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/icon_arrow_right.png
--------------------------------------------------------------------------------
/assets/images/3.0x/icon_ffwd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/icon_ffwd.png
--------------------------------------------------------------------------------
/assets/images/3.0x/login_screen_account.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/login_screen_account.png
--------------------------------------------------------------------------------
/assets/images/3.0x/login_screen_password.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/login_screen_password.png
--------------------------------------------------------------------------------
/assets/images/3.0x/login_screen_server_url.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/login_screen_server_url.png
--------------------------------------------------------------------------------
/assets/images/3.0x/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/logo.png
--------------------------------------------------------------------------------
/assets/images/3.0x/settings_screen_about.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/settings_screen_about.png
--------------------------------------------------------------------------------
/assets/images/3.0x/settings_screen_account.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/settings_screen_account.png
--------------------------------------------------------------------------------
/assets/images/3.0x/settings_screen_cache_manager.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/settings_screen_cache_manager.png
--------------------------------------------------------------------------------
/assets/images/3.0x/settings_screen_donate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/settings_screen_donate.png
--------------------------------------------------------------------------------
/assets/images/3.0x/settings_screen_download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/settings_screen_download.png
--------------------------------------------------------------------------------
/assets/images/3.0x/settings_screen_player.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/settings_screen_player.png
--------------------------------------------------------------------------------
/assets/images/3.0x/settings_screen_privacy_policy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/3.0x/settings_screen_privacy_policy.png
--------------------------------------------------------------------------------
/assets/images/account_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/account_icon.png
--------------------------------------------------------------------------------
/assets/images/account_icon_choosed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/account_icon_choosed.png
--------------------------------------------------------------------------------
/assets/images/file_type_apk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/file_type_apk.png
--------------------------------------------------------------------------------
/assets/images/file_type_audio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/file_type_audio.png
--------------------------------------------------------------------------------
/assets/images/file_type_code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/file_type_code.png
--------------------------------------------------------------------------------
/assets/images/file_type_docment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/file_type_docment.png
--------------------------------------------------------------------------------
/assets/images/file_type_excel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/file_type_excel.png
--------------------------------------------------------------------------------
/assets/images/file_type_folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/file_type_folder.png
--------------------------------------------------------------------------------
/assets/images/file_type_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/file_type_image.png
--------------------------------------------------------------------------------
/assets/images/file_type_md.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/file_type_md.png
--------------------------------------------------------------------------------
/assets/images/file_type_pdf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/file_type_pdf.png
--------------------------------------------------------------------------------
/assets/images/file_type_ppt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/file_type_ppt.png
--------------------------------------------------------------------------------
/assets/images/file_type_unknow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/file_type_unknow.png
--------------------------------------------------------------------------------
/assets/images/file_type_video.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/file_type_video.png
--------------------------------------------------------------------------------
/assets/images/file_type_word.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/file_type_word.png
--------------------------------------------------------------------------------
/assets/images/file_type_zip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/file_type_zip.png
--------------------------------------------------------------------------------
/assets/images/ic_infuse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/ic_infuse.png
--------------------------------------------------------------------------------
/assets/images/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/ic_launcher.png
--------------------------------------------------------------------------------
/assets/images/ic_nplayer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/ic_nplayer.png
--------------------------------------------------------------------------------
/assets/images/ic_vlc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/ic_vlc.png
--------------------------------------------------------------------------------
/assets/images/icon_arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/icon_arrow_right.png
--------------------------------------------------------------------------------
/assets/images/icon_ffwd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/icon_ffwd.png
--------------------------------------------------------------------------------
/assets/images/login_screen_account.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/login_screen_account.png
--------------------------------------------------------------------------------
/assets/images/login_screen_password.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/login_screen_password.png
--------------------------------------------------------------------------------
/assets/images/login_screen_server_url.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/login_screen_server_url.png
--------------------------------------------------------------------------------
/assets/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/logo.png
--------------------------------------------------------------------------------
/assets/images/settings_screen_about.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/settings_screen_about.png
--------------------------------------------------------------------------------
/assets/images/settings_screen_account.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/settings_screen_account.png
--------------------------------------------------------------------------------
/assets/images/settings_screen_cache_manager.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/settings_screen_cache_manager.png
--------------------------------------------------------------------------------
/assets/images/settings_screen_donate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/settings_screen_donate.png
--------------------------------------------------------------------------------
/assets/images/settings_screen_download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/settings_screen_download.png
--------------------------------------------------------------------------------
/assets/images/settings_screen_player.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/settings_screen_player.png
--------------------------------------------------------------------------------
/assets/images/settings_screen_privacy_policy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/assets/images/settings_screen_privacy_policy.png
--------------------------------------------------------------------------------
/generateKeys:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/generateKeys
--------------------------------------------------------------------------------
/github/android_github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/github/android_github.png
--------------------------------------------------------------------------------
/github/appstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/github/appstore.png
--------------------------------------------------------------------------------
/github/banner.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/github/banner.jpg
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | **/dgph
2 | *.mode1v3
3 | *.mode2v3
4 | *.moved-aside
5 | *.pbxuser
6 | *.perspectivev3
7 | **/*sync/
8 | .sconsign.dblite
9 | .tags*
10 | **/.vagrant/
11 | **/DerivedData/
12 | Icon?
13 | **/Pods/
14 | **/.symlinks/
15 | profile
16 | xcuserdata
17 | **/.generated/
18 | Flutter/App.framework
19 | Flutter/Flutter.framework
20 | Flutter/Flutter.podspec
21 | Flutter/Generated.xcconfig
22 | Flutter/ephemeral/
23 | Flutter/app.flx
24 | Flutter/app.zip
25 | Flutter/flutter_assets/
26 | Flutter/flutter_export_environment.sh
27 | ServiceDefinitions.json
28 | Runner/GeneratedPluginRegistrant.*
29 |
30 | # Exceptions to above rules.
31 | !default.mode1v3
32 | !default.mode2v3
33 | !default.pbxuser
34 | !default.perspectivev3
35 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 12.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '12.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | use_frameworks!
32 | use_modular_headers!
33 |
34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
35 | end
36 |
37 | post_install do |installer|
38 | installer.pods_project.targets.each do |target|
39 | flutter_additional_ios_build_settings(target)
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ios/Runner/AppSupportFiles/license.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN ALI VIDEO CERT-----
2 | LmlsQS5jaUwAAWRjY2FhYTU1OTAxNzE0NDg2OWJlOGJkNzczZTc5ZjAzM2YwMDhiO
3 | WY5ODUwNTc5MGY4NDEyOTRiMzNjMmZiYjg1NGUxZThlNjAwNzRmNTgxZTU0MDY2Mj
4 | RiMGFiM2JkNWVmOTE3ZDE0MDJlNDQ0ZDUwNmExMTc5ZjFlYjYyODQ2MDRiYzdiYjA
5 | zOTI2ZjYyOTE1OWVjYjY0ZDk1ZDhhN2Q5ZWZlOTRjOTdkMTA0Yzc1MWU5OGEwNGY3
6 | OTdkOTdiYTAzMWEyMDFlMzc2Mjg0NGI1MTEyYWRkZDQzNTgyZDA2NTJkYTk0MDk1Y
7 | TIxYjY2NWJmYjY0ZTkwMWQyZGNjNmVjMjY1ODFkYmJjZjBhY2ZmZjFhNDU3NTJjND
8 | QwNTMzZmJlZDk3YTIzMmMyOWQ4YWVkZDY0YmZhZDc2ZDY1MTRiZGU5MmM3YTdjMGZ
9 | iYjI3OTNhNjZiMDEzMjBkODgxYzBhMjA1YTExN2Q1YmU3ZTgyMzYyYzI5MDJhZDNk
10 | MmFiZTcxNTQ5NzI2YzI4NTVjOTc5MWVmZDVjMGU4NDZmMDZlZDhlYTY1MjgzYWUzM
11 | 2JkOTYzOWJiZTkwOGU4ZTBmY2QwNDc1OWQ5N2U3OTk1NDNhMzdkNDQ2YzZlMDJhMj
12 | BkODI2YTUzZGIzNTNjNWU3MDVjYmJmYzg5ODVjYjRkMWIxAAABj06iJAA/+Gshl5B
13 | eEiWwHuBRORrQ9Nifz09+LrM1FjMpjew1Sb4g/9DXPrpbbPp/Um6uSb+TOl9ZchoT
14 | rckfqr2AgEomg1oH2WTy5teWsYBX2dSFCWzr+qFGqtLZWFjvAID+dkh4J1zt/2GGQ
15 | Cy0ah1fJZXYdkzVK/NmRn8dL4sJnaGrr46iPTKlUvQAZZw4VRDtcYjepMWCGuUJFn
16 | WLS5uIIjYBVX7cOATAJpd+At64LG5Pvnq9NnqSo5KY/zh4p6UitA7wyOAMyzwRaEw
17 | qpo+rtR/uKVau0gGrXz+Z19ZiqFJXoOxkLJDhjXiAUzi5FjAOZmYkiuYZ57gtGcXW
18 | WrBsrfbOAAABQH18wrod6jHXVoSNhov+rpNnu59d4F1BwyVBObUfH99fA5iEJZ1AQ
19 | I1Zuu6q/98lQkRNj+iTeuFSUo8s+DYk3dkzeEsy247nzwlVjBC5/eahiOGUhTtVOV
20 | W2RmcpuuoylqDs4qhDC7on6QPJ9v3qwudKM3W+77AM2RRqpLYH87IC1JzppfTV3Ve
21 | oUzFd/e4UEANVSSJ9WgvvuGQ3cOnY+eA6ScHPGqteIL1BW3FzC06jH3E2QQ+cQqUK
22 | 1d83qTCyJ+wtXuXAxgT2qJXS/b3pP3e4MCeO+AUD8TMBzDECkPsVH4QtWvLsvEVPs
23 | AYuxy48qymnOPinlMfg5CS7/pqa5h8AAAGH9lAVYAAAAHYAAAAgZ2U3YjUyY2M3MT
24 | BmNDcwYTk5MTMyMzVmNTY4ZmRiNzYAAAACAAAAIwAAAAAAAAACAAAAF2NvbS5naXR
25 | odWIuYWxpc3QuY2xpZW50AAAAIwAAAAAAAAABAAAAF2NvbS5naXRodWIuYWxpc3Qu
26 | Y2xpZW50AAAAAgAAAF0AAAACAAAAAAAAAAEAACPxAAABj1PIgAAAAAAAQAAAAAEAA
27 | AACAAAAGAAATiEAAAGH9lAMsAAAAY9TyIAAAAAAAAAAABgAAE4iAAABh/ZQDLAAAA
28 | GPU8iAAAAAAAAAAABdAAAAAgAAAAAAAAACAAAj8QAAAY9TyIAAAAAAAEAAAAABAAA
29 | AAgAAABgAAE4hAAABh/ZQDLAAAAGPU8iAAAAAAAAAAAAYAABOIgAAAYf2UAywAAAB
30 | j1PIgAAAAAAA
31 | -----END ALI VIDEO CERT-----
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/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/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/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/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/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/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/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/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/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/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/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/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/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/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/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/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/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/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/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/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/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/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-iTunes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-iTunes.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "ic_splash_ios.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "ic_splash_ios@2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "ic_splash_ios@3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/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/Assets.xcassets/LaunchImage.imageset/ic_splash_ios.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/ios/Runner/Assets.xcassets/LaunchImage.imageset/ic_splash_ios.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/ic_splash_ios@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/ios/Runner/Assets.xcassets/LaunchImage.imageset/ic_splash_ios@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/ic_splash_ios@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/ios/Runner/Assets.xcassets/LaunchImage.imageset/ic_splash_ios@3x.png
--------------------------------------------------------------------------------
/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 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AlivcLicenseFile
6 | license.crt
7 | AlivcLicenseKey
8 | 7od4xPYaUwm4scy4t57cd70e56f2d4196aed4167e6e4174c9
9 | CADisableMinimumFrameDurationOnPhone
10 |
11 | CFBundleSignature
12 | ????
13 | LSHasLocalizedDisplayName
14 |
15 | NSAppTransportSecurity
16 |
17 | NSAllowsArbitraryLoads
18 |
19 |
20 | UIViewControllerBasedStatusBarAppearance
21 |
22 | io.flutter.embedded_views_preview
23 |
24 | UIApplicationSupportsIndirectInputEvents
25 |
26 | NSPhotoLibraryUsageDescription
27 | ALClient needs permission to access photos on your device
28 | NSPhotoLibraryAddUsageDescription
29 | ALClient needs permission to add photos to your device
30 | NSCameraUsageDescription>
31 | Photo/video upload function requires you to grant camera access
32 | NSMicrophoneUsageDescription
33 | The video/recording upload feature requires you to grant microphone access
34 | UIBackgroundModes
35 |
36 | audio
37 |
38 | UIFileSharingEnabled
39 |
40 | LSSupportsOpeningDocumentsInPlace
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/ios/Runner/Runner.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/ios/Runner/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /*
2 | InfoPlist.strings
3 | Runner
4 |
5 | Created by tangrui on 2023/6/15.
6 |
7 | */
8 | NSPhotoLibraryUsageDescription = "Uploading pictures/videos requires you to grant access to the album";
9 | NSCameraUsageDescription = "Photo/video upload function requires you to grant camera access";
10 | NSMicrophoneUsageDescription = "The video/recording upload feature requires you to grant microphone access";
11 |
--------------------------------------------------------------------------------
/ios/Runner/zh-Hans.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /*
2 | InfoPlist.strings
3 | Runner
4 |
5 | Created by tangrui on 2023/6/15.
6 |
7 | */
8 | NSPhotoLibraryUsageDescription = "上传图片/视频功能需要您授予相册访问权限";
9 | NSCameraUsageDescription = "拍照/拍视频上传功能需要您授予相机权限";
10 | NSMicrophoneUsageDescription = "录视频/录音上传功能需要您授予麦克风权限";
11 |
--------------------------------------------------------------------------------
/ios/Runner/zh-Hans.lproj/LaunchScreen.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/ios/Runner/zh-Hans.lproj/Main.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/lib/database/alist_database.dart:
--------------------------------------------------------------------------------
1 | // database.dart
2 |
3 | import 'dart:async';
4 |
5 | import 'package:alist/database/dao/favorite_dao.dart';
6 | import 'package:alist/database/dao/file_download_record_dao.dart';
7 | import 'package:alist/database/dao/file_password_dao.dart';
8 | import 'package:alist/database/dao/file_viewing_record_dao.dart';
9 | import 'package:alist/database/dao/server_dao.dart';
10 | import 'package:alist/database/table/favorite.dart';
11 | import 'package:alist/database/table/file_download_record.dart';
12 | import 'package:alist/database/table/file_password.dart';
13 | import 'package:alist/database/table/file_viewing_record.dart';
14 | import 'package:alist/database/table/server.dart';
15 | import 'package:floor/floor.dart';
16 | import 'package:sqflite/sqflite.dart' as sqflite;
17 |
18 | import 'dao/video_viewing_record_dao.dart';
19 | import 'table/video_viewing_record.dart';
20 |
21 | part 'alist_database.g.dart'; // the generated code will be there
22 |
23 | @Database(version: 5, entities: [
24 | VideoViewingRecord,
25 | FileDownloadRecord,
26 | FilePassword,
27 | Server,
28 | FileViewingRecord,
29 | Favorite,
30 | ])
31 | abstract class AlistDatabase extends FloorDatabase {
32 | VideoViewingRecordDao get videoViewingRecordDao;
33 |
34 | FileDownloadRecordRecordDao get downloadRecordRecordDao;
35 |
36 | FilePasswordDao get filePasswordDao;
37 |
38 | ServerDao get serverDao;
39 |
40 | FileViewingRecordDao get fileViewingRecordDao;
41 |
42 | FavoriteDao get favoriteDao;
43 | }
44 |
--------------------------------------------------------------------------------
/lib/database/dao/favorite_dao.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/database/table/favorite.dart';
2 | import 'package:floor/floor.dart';
3 |
4 | @dao
5 | abstract class FavoriteDao {
6 | @insert
7 | Future insertRecord(Favorite favorite);
8 |
9 | @update
10 | Future updateRecord(Favorite favorite);
11 |
12 | @update
13 | Future updateRecords(List favorite);
14 |
15 | @delete
16 | Future deleteRecord(Favorite favorite);
17 |
18 | @Query(
19 | "SELECT * FROM favorite WHERE server_url = :serverUrl AND user_id=:userId AND path=:path LIMIT 1")
20 | Future findByPath(
21 | String serverUrl,
22 | String userId,
23 | String path,
24 | );
25 |
26 | @Query(
27 | "SELECT * FROM favorite WHERE server_url = :serverUrl AND user_id=:userId ORDER BY id DESC")
28 | Stream?> list(
29 | String serverUrl,
30 | String userId,
31 | );
32 |
33 | @Query("SELECT COUNT(id) FROM favorite")
34 | Stream countStream();
35 |
36 | @Query(
37 | "DELETE FROM favorite WHERE server_url = :serverUrl AND user_id=:userId AND remote_path=:remotePath")
38 | Future deleteByPath(
39 | String serverUrl,
40 | String userId,
41 | String remotePath,
42 | );
43 | }
44 |
--------------------------------------------------------------------------------
/lib/database/dao/file_download_record_dao.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/database/table/file_download_record.dart';
2 | import 'package:floor/floor.dart';
3 |
4 | @dao
5 | abstract class FileDownloadRecordRecordDao {
6 | @insert
7 | Future insertRecord(FileDownloadRecord record);
8 |
9 | @update
10 | Future updateRecord(FileDownloadRecord record);
11 |
12 | @delete
13 | Future deleteRecord(FileDownloadRecord record);
14 |
15 | @Query("DELETE FROM file_download_record WHERE id = :id")
16 | Future deleteById(int id);
17 |
18 | @Query(
19 | "SELECT * FROM file_download_record WHERE server_url = :serverUrl AND user_id=:userId AND sign=:sign LIMIT 1")
20 | Future findRecordBySign(
21 | String serverUrl,
22 | String userId,
23 | String sign,
24 | );
25 |
26 | @Query(
27 | "SELECT * FROM file_download_record WHERE server_url = :serverUrl AND user_id=:userId AND remote_path=:remotePath LIMIT 1")
28 | Future findRecordByRemotePath(
29 | String serverUrl,
30 | String userId,
31 | String remotePath,
32 | );
33 |
34 | @Query(
35 | "SELECT * FROM file_download_record WHERE server_url = :serverUrl AND user_id=:userId ORDER BY id DESC")
36 | Future?> findAll(String serverUrl, String userId);
37 |
38 | @Query(
39 | "UPDATE file_download_record SET local_path = :newLocalPath WHERE id = :id")
40 | Future updateLocalPath(int id, String newLocalPath);
41 | }
42 |
--------------------------------------------------------------------------------
/lib/database/dao/file_password_dao.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/database/table/file_download_record.dart';
2 | import 'package:alist/database/table/file_password.dart';
3 | import 'package:floor/floor.dart';
4 |
5 | @dao
6 | abstract class FilePasswordDao {
7 | @insert
8 | Future insertFilePassword(FilePassword filePassword);
9 |
10 | @update
11 | Future updateFilePassword(FilePassword filePassword);
12 |
13 | @delete
14 | Future deleteFilePassword(FilePassword filePassword);
15 |
16 | @Query("DELETE FROM file_password WHERE server_url = :serverUrl AND user_id=:userId AND remote_path=:remotePath")
17 | Future deleteByPath(String serverUrl, String userId, String remotePath);
18 |
19 | @Query(
20 | "SELECT * FROM file_password WHERE server_url = :serverUrl AND user_id=:userId AND remote_path=:remotePath ORDER BY id DESC LIMIT 1")
21 | Future findPasswordByPath(
22 | String serverUrl,
23 | String userId,
24 | String remotePath,
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/lib/database/dao/file_viewing_record_dao.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/database/table/file_viewing_record.dart';
2 | import 'package:floor/floor.dart';
3 |
4 | @dao
5 | abstract class FileViewingRecordDao {
6 | @insert
7 | Future insertRecord(FileViewingRecord record);
8 |
9 | @update
10 | Future updateRecord(FileViewingRecord record);
11 |
12 | @update
13 | Future updateRecords(List record);
14 |
15 | @delete
16 | Future deleteRecord(FileViewingRecord record);
17 |
18 | @Query(
19 | "SELECT * FROM file_viewing_record WHERE server_url = :serverUrl AND user_id=:userId ORDER BY id DESC LIMIT 100")
20 | Stream?> recordList(
21 | String serverUrl,
22 | String userId,
23 | );
24 |
25 | @Query(
26 | "DELETE FROM file_viewing_record WHERE server_url = :serverUrl AND user_id=:userId AND remote_path=:remotePath")
27 | Future deleteByPath(
28 | String serverUrl,
29 | String userId,
30 | String remotePath,
31 | );
32 | }
33 |
--------------------------------------------------------------------------------
/lib/database/dao/server_dao.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/database/table/server.dart';
2 | import 'package:floor/floor.dart';
3 |
4 | @dao
5 | abstract class ServerDao {
6 | @insert
7 | Future insertServer(Server server);
8 |
9 | @update
10 | Future updateServer(Server server);
11 |
12 | @delete
13 | Future deleteServer(Server server);
14 |
15 | @Query(
16 | "SELECT * FROM server WHERE server_url = :serverUrl AND user_id=:userId LIMIT 1")
17 | Future findServer(String serverUrl, String userId);
18 |
19 | @Query("SELECT * FROM server ORDER BY id desc LIMIT 100")
20 | Stream?> serverList();
21 | }
22 |
--------------------------------------------------------------------------------
/lib/database/dao/video_viewing_record_dao.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/database/table/video_viewing_record.dart';
2 | import 'package:floor/floor.dart';
3 |
4 | @dao
5 | abstract class VideoViewingRecordDao {
6 | @insert
7 | Future insertRecord(VideoViewingRecord record);
8 |
9 | @update
10 | Future updateRecord(VideoViewingRecord record);
11 |
12 | @delete
13 | Future deleteRecord(VideoViewingRecord record);
14 |
15 | @Query(
16 | "SELECT * FROM video_viewing_record WHERE server_url = :serverUrl AND user_id=:userId AND path=:path LIMIT 1")
17 | Future findRecordByPath(
18 | String serverUrl,
19 | String userId,
20 | String path,
21 | );
22 | }
23 |
--------------------------------------------------------------------------------
/lib/database/table/favorite.dart:
--------------------------------------------------------------------------------
1 | import 'package:floor/floor.dart';
2 |
3 | @Entity(tableName: "favorite")
4 | class Favorite {
5 | @PrimaryKey(autoGenerate: true)
6 | final int? id;
7 |
8 | @ColumnInfo(name: 'is_dir')
9 | final bool isDir;
10 |
11 | @ColumnInfo(name: 'server_url')
12 | final String serverUrl;
13 |
14 | @ColumnInfo(name: 'user_id')
15 | final String userId;
16 |
17 | @ColumnInfo(name: 'remote_path')
18 | final String remotePath;
19 |
20 | @ColumnInfo(name: 'name')
21 | final String name;
22 |
23 | @ColumnInfo(name: 'size')
24 | final int size;
25 |
26 | @ColumnInfo(name: 'sign')
27 | final String? sign;
28 |
29 | @ColumnInfo(name: 'thumb')
30 | final String? thumb;
31 |
32 | @ColumnInfo(name: 'modified')
33 | final int modified;
34 |
35 | @ColumnInfo(name: 'provider')
36 | final String provider;
37 |
38 | @ColumnInfo(name: 'create_time')
39 | final int createTime;
40 |
41 | @ColumnInfo(name: 'path')
42 | final String path;
43 |
44 | Favorite({
45 | this.id,
46 | required this.isDir,
47 | required this.serverUrl,
48 | required this.userId,
49 | required this.remotePath,
50 | required this.name,
51 | required this.path,
52 | required this.size,
53 | required this.sign,
54 | required this.thumb,
55 | required this.modified,
56 | required this.provider,
57 | required this.createTime,
58 | });
59 | }
60 |
--------------------------------------------------------------------------------
/lib/database/table/file_download_record.dart:
--------------------------------------------------------------------------------
1 | import 'package:floor/floor.dart';
2 |
3 | @Entity(tableName: "file_download_record")
4 | class FileDownloadRecord {
5 | @PrimaryKey(autoGenerate: true)
6 | int? id;
7 |
8 | @ColumnInfo(name: 'server_url')
9 | final String serverUrl;
10 |
11 | @ColumnInfo(name: 'user_id')
12 | final String userId;
13 |
14 | @ColumnInfo(name: 'remote_path')
15 | final String remotePath;
16 |
17 | @ColumnInfo(name: 'sign')
18 | final String sign;
19 |
20 | @ColumnInfo(name: 'name')
21 | final String name;
22 |
23 | @ColumnInfo(name: 'local_path')
24 | final String localPath;
25 |
26 | @ColumnInfo(name: 'create_time')
27 | final int createTime;
28 |
29 | @ColumnInfo(name: 'thumbnail')
30 | final String? thumbnail;
31 |
32 | @ColumnInfo(name: 'request_headers')
33 | final String? requestHeaders;
34 |
35 | // 下载频率限制,单位 秒
36 | @ColumnInfo(name: 'limit_frequency')
37 | final int? limitFrequency;
38 |
39 | @ColumnInfo(name: 'finished')
40 | bool? finished;
41 |
42 | FileDownloadRecord({
43 | this.id,
44 | required this.serverUrl,
45 | required this.userId,
46 | required this.remotePath,
47 | required this.sign,
48 | required this.name,
49 | required this.localPath,
50 | required this.createTime,
51 | required this.thumbnail,
52 | required this.requestHeaders,
53 | required this.limitFrequency,
54 | this.finished
55 | });
56 | }
57 |
--------------------------------------------------------------------------------
/lib/database/table/file_password.dart:
--------------------------------------------------------------------------------
1 | import 'package:floor/floor.dart';
2 |
3 | @Entity(tableName: "file_password")
4 | class FilePassword {
5 | @PrimaryKey(autoGenerate: true)
6 | final int? id;
7 |
8 | @ColumnInfo(name: 'server_url')
9 | final String serverUrl;
10 |
11 | @ColumnInfo(name: 'user_id')
12 | final String userId;
13 |
14 | @ColumnInfo(name: 'remote_path')
15 | final String remotePath;
16 |
17 | @ColumnInfo(name: 'password')
18 | final String password;
19 |
20 | @ColumnInfo(name: 'create_time')
21 | final int createTime;
22 |
23 | FilePassword({
24 | this.id,
25 | required this.serverUrl,
26 | required this.userId,
27 | required this.remotePath,
28 | required this.password,
29 | required this.createTime,
30 | });
31 | }
32 |
--------------------------------------------------------------------------------
/lib/database/table/file_viewing_record.dart:
--------------------------------------------------------------------------------
1 | import 'package:floor/floor.dart';
2 |
3 | @Entity(tableName: "file_viewing_record")
4 | class FileViewingRecord {
5 | @PrimaryKey(autoGenerate: true)
6 | final int? id;
7 |
8 | @ColumnInfo(name: 'server_url')
9 | final String serverUrl;
10 |
11 | @ColumnInfo(name: 'user_id')
12 | final String userId;
13 |
14 | @ColumnInfo(name: 'remote_path')
15 | final String remotePath;
16 |
17 | @ColumnInfo(name: 'name')
18 | final String name;
19 |
20 | @ColumnInfo(name: 'size')
21 | final int size;
22 |
23 | @ColumnInfo(name: 'sign')
24 | final String? sign;
25 |
26 | @ColumnInfo(name: 'thumb')
27 | final String? thumb;
28 |
29 | @ColumnInfo(name: 'modified')
30 | final int modified;
31 |
32 | @ColumnInfo(name: 'provider')
33 | final String provider;
34 |
35 | @ColumnInfo(name: 'create_time')
36 | final int createTime;
37 |
38 | @ColumnInfo(name: 'path')
39 | final String path;
40 |
41 | FileViewingRecord({
42 | this.id,
43 | required this.serverUrl,
44 | required this.userId,
45 | required this.remotePath,
46 | required this.name,
47 | required this.path,
48 | required this.size,
49 | required this.sign,
50 | required this.thumb,
51 | required this.modified,
52 | required this.provider,
53 | required this.createTime,
54 | });
55 | }
56 |
--------------------------------------------------------------------------------
/lib/database/table/server.dart:
--------------------------------------------------------------------------------
1 | import 'package:floor/floor.dart';
2 |
3 | @Entity(tableName: "server")
4 | class Server {
5 | @PrimaryKey(autoGenerate: true)
6 | final int? id;
7 |
8 | @ColumnInfo(name: 'name')
9 | final String name;
10 |
11 | @ColumnInfo(name: 'server_url')
12 | final String serverUrl;
13 |
14 | @ColumnInfo(name: 'user_id')
15 | final String userId;
16 |
17 | @ColumnInfo(name: 'password')
18 | final String password;
19 |
20 | @ColumnInfo(name: 'token')
21 | final String token;
22 |
23 | @ColumnInfo(name: 'guest')
24 | final bool guest;
25 |
26 | @ColumnInfo(name: 'ignore_ssl_error')
27 | final bool ignoreSSLError;
28 |
29 | @ColumnInfo(name: 'create_time')
30 | final int createTime;
31 |
32 | @ColumnInfo(name: 'update_time')
33 | final int updateTime;
34 |
35 | Server({
36 | this.id,
37 | required this.name,
38 | required this.serverUrl,
39 | required this.userId,
40 | required this.password,
41 | required this.token,
42 | required this.guest,
43 | required this.ignoreSSLError,
44 | required this.createTime,
45 | required this.updateTime,
46 | });
47 | }
48 |
--------------------------------------------------------------------------------
/lib/database/table/video_viewing_record.dart:
--------------------------------------------------------------------------------
1 | import 'package:floor/floor.dart';
2 |
3 | @Entity(tableName: "video_viewing_record")
4 | class VideoViewingRecord {
5 | @PrimaryKey(autoGenerate: true)
6 | final int? id;
7 |
8 | @ColumnInfo(name: 'server_url')
9 | final String serverUrl;
10 |
11 | @ColumnInfo(name: 'user_id')
12 | final String userId;
13 |
14 | @ColumnInfo(name: 'video_sign')
15 | final String videoSign;
16 |
17 | @ColumnInfo(name: 'path')
18 | final String path;
19 |
20 | @ColumnInfo(name: 'video_duration')
21 | final int videoDuration;
22 |
23 | @ColumnInfo(name: 'video_current_position')
24 | final int videoCurrentPosition;
25 |
26 | VideoViewingRecord({
27 | this.id,
28 | required this.serverUrl,
29 | required this.userId,
30 | required this.videoSign,
31 | required this.path,
32 | required this.videoDuration,
33 | required this.videoCurrentPosition,
34 | });
35 | }
36 |
--------------------------------------------------------------------------------
/lib/entity/app_version_resp.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_field.dart';
2 | import 'package:alist/generated/json/app_version_resp.g.dart';
3 | import 'dart:convert';
4 |
5 | @JsonSerializable()
6 | class AppVersionResp {
7 | late String updates;
8 | late AppVersionRespAndroid android;
9 | late AppVersionRespIos ios;
10 |
11 | AppVersionResp();
12 |
13 | factory AppVersionResp.fromJson(Map json) => $AppVersionRespFromJson(json);
14 |
15 | Map toJson() => $AppVersionRespToJson(this);
16 |
17 | @override
18 | String toString() {
19 | return jsonEncode(this);
20 | }
21 | }
22 |
23 | @JsonSerializable()
24 | class AppVersionRespAndroid {
25 | late String version;
26 | late String githubUrl;
27 | late String googlePlayUrl;
28 |
29 | AppVersionRespAndroid();
30 |
31 | factory AppVersionRespAndroid.fromJson(Map json) => $AppVersionRespAndroidFromJson(json);
32 |
33 | Map toJson() => $AppVersionRespAndroidToJson(this);
34 |
35 | @override
36 | String toString() {
37 | return jsonEncode(this);
38 | }
39 | }
40 |
41 | @JsonSerializable()
42 | class AppVersionRespIos {
43 | late String version;
44 | late String appStoreUrl;
45 |
46 | AppVersionRespIos();
47 |
48 | factory AppVersionRespIos.fromJson(Map json) => $AppVersionRespIosFromJson(json);
49 |
50 | Map toJson() => $AppVersionRespIosToJson(this);
51 |
52 | @override
53 | String toString() {
54 | return jsonEncode(this);
55 | }
56 | }
--------------------------------------------------------------------------------
/lib/entity/copy_move_req.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_field.dart';
2 | import 'package:alist/generated/json/copy_move_req.g.dart';
3 | import 'dart:convert';
4 |
5 | @JsonSerializable()
6 | class CopyMoveReq {
7 | @JSONField(name: "src_dir")
8 | late String srcDir;
9 | @JSONField(name: "dst_dir")
10 | late String dstDir;
11 | late List names;
12 |
13 | CopyMoveReq();
14 |
15 | factory CopyMoveReq.fromJson(Map json) => $CopyMoveReqFromJson(json);
16 |
17 | Map toJson() => $CopyMoveReqToJson(this);
18 |
19 | @override
20 | String toString() {
21 | return jsonEncode(this);
22 | }
23 | }
--------------------------------------------------------------------------------
/lib/entity/donate_config_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_field.dart';
2 | import 'package:alist/generated/json/donate_config_entity.g.dart';
3 | import 'dart:convert';
4 |
5 | @JsonSerializable()
6 | class DonateConfigEntity {
7 | late String wechat;
8 | @JSONField(name: "wechat_small")
9 | late String wechatSmall;
10 | late String alipay;
11 | @JSONField(name: "alipay_small")
12 | late String alipaySmall;
13 |
14 | DonateConfigEntity();
15 |
16 | factory DonateConfigEntity.fromJson(Map json) => $DonateConfigEntityFromJson(json);
17 |
18 | Map toJson() => $DonateConfigEntityToJson(this);
19 |
20 | @override
21 | String toString() {
22 | return jsonEncode(this);
23 | }
24 | }
--------------------------------------------------------------------------------
/lib/entity/downloads_info.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_field.dart';
2 | import 'package:alist/generated/json/downloads_info.g.dart';
3 | import 'dart:convert';
4 |
5 | @JsonSerializable()
6 | class DownloadsInfo {
7 | late bool isSupportRange;
8 | late bool decompress;
9 | String? lastModified;
10 | String? etag;
11 | int? contentLength;
12 |
13 | DownloadsInfo();
14 |
15 | factory DownloadsInfo.fromJson(Map json) =>
16 | $DownloadsInfoFromJson(json);
17 |
18 | Map toJson() => $DownloadsInfoToJson(this);
19 |
20 | @override
21 | String toString() {
22 | return jsonEncode(this);
23 | }
24 | }
--------------------------------------------------------------------------------
/lib/entity/file_info_resp_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_field.dart';
2 | import 'package:alist/generated/json/file_info_resp_entity.g.dart';
3 | import 'dart:convert';
4 |
5 | @JsonSerializable()
6 | class FileInfoRespEntity {
7 | late String name;
8 | late int size;
9 | @JSONField(name: "is_dir")
10 | late bool isDir;
11 | late String modified;
12 | late String sign;
13 | late String thumb;
14 | late int type;
15 | @JSONField(name: "raw_url")
16 | late String rawUrl;
17 | late String readme;
18 | late String provider;
19 | dynamic related;
20 |
21 | FileInfoRespEntity();
22 |
23 | factory FileInfoRespEntity.fromJson(Map json) => $FileInfoRespEntityFromJson(json);
24 |
25 | Map toJson() => $FileInfoRespEntityToJson(this);
26 |
27 | @override
28 | String toString() {
29 | return jsonEncode(this);
30 | }
31 | }
--------------------------------------------------------------------------------
/lib/entity/file_list_resp_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_field.dart';
2 | import 'package:alist/generated/json/file_list_resp_entity.g.dart';
3 | import 'dart:convert';
4 |
5 | @JsonSerializable()
6 | class FileListRespEntity {
7 | List? content;
8 | late int total;
9 | late String readme;
10 | late bool write;
11 | late String provider;
12 |
13 | FileListRespEntity();
14 |
15 | factory FileListRespEntity.fromJson(Map json) => $FileListRespEntityFromJson(json);
16 |
17 | Map toJson() => $FileListRespEntityToJson(this);
18 |
19 | @override
20 | String toString() {
21 | return jsonEncode(this);
22 | }
23 | }
24 |
25 | @JsonSerializable()
26 | class FileListRespContent {
27 | late String name;
28 | int? size;
29 | @JSONField(name: "is_dir")
30 | late bool isDir;
31 | late String modified;
32 | late String sign;
33 | late String thumb;
34 | late int type;
35 | String? readme;
36 |
37 | FileListRespContent();
38 |
39 | factory FileListRespContent.fromJson(Map json) => $FileListRespContentFromJson(json);
40 |
41 | Map toJson() => $FileListRespContentToJson(this);
42 |
43 | @override
44 | String toString() {
45 | return jsonEncode(this);
46 | }
47 | }
--------------------------------------------------------------------------------
/lib/entity/file_remove_req.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_field.dart';
2 | import 'package:alist/generated/json/file_remove_req.g.dart';
3 | import 'dart:convert';
4 |
5 | @JsonSerializable()
6 | class FileRemoveReq {
7 | late String dir;
8 | late List names;
9 |
10 | FileRemoveReq();
11 |
12 | factory FileRemoveReq.fromJson(Map json) => $FileRemoveReqFromJson(json);
13 |
14 | Map toJson() => $FileRemoveReqToJson(this);
15 |
16 | @override
17 | String toString() {
18 | return jsonEncode(this);
19 | }
20 | }
--------------------------------------------------------------------------------
/lib/entity/file_rename_req.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_field.dart';
2 | import 'package:alist/generated/json/file_rename_req.g.dart';
3 | import 'dart:convert';
4 |
5 | @JsonSerializable()
6 | class FileRenameReq {
7 | late String path;
8 | late String name;
9 |
10 | FileRenameReq();
11 |
12 | factory FileRenameReq.fromJson(Map json) => $FileRenameReqFromJson(json);
13 |
14 | Map toJson() => $FileRenameReqToJson(this);
15 |
16 | @override
17 | String toString() {
18 | return jsonEncode(this);
19 | }
20 | }
--------------------------------------------------------------------------------
/lib/entity/file_search_resp.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_field.dart';
2 | import 'package:alist/generated/json/file_search_resp.g.dart';
3 | import 'dart:convert';
4 | export 'package:alist/generated/json/file_search_resp.g.dart';
5 |
6 | @JsonSerializable()
7 | class FileSearchResp {
8 | List? content;
9 | int? total;
10 |
11 | FileSearchResp();
12 |
13 | factory FileSearchResp.fromJson(Map json) => $FileSearchRespFromJson(json);
14 |
15 | Map toJson() => $FileSearchRespToJson(this);
16 |
17 | @override
18 | String toString() {
19 | return jsonEncode(this);
20 | }
21 | }
22 |
23 | @JsonSerializable()
24 | class FileSearchRespContent {
25 | String? parent;
26 | String? name;
27 | @JSONField(name: "is_dir")
28 | bool? isDir;
29 | int? size;
30 | int? type;
31 |
32 | FileSearchRespContent();
33 |
34 | factory FileSearchRespContent.fromJson(Map json) => $FileSearchRespContentFromJson(json);
35 |
36 | Map toJson() => $FileSearchRespContentToJson(this);
37 |
38 | @override
39 | String toString() {
40 | return jsonEncode(this);
41 | }
42 | }
--------------------------------------------------------------------------------
/lib/entity/http_result.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_convert_content.dart';
2 |
3 | class HttpResult {
4 | late int code;
5 | late String message;
6 | T? data;
7 |
8 | HttpResult(this.code, this.message, this.data);
9 |
10 | HttpResult.fromJson(Map json) {
11 | code = json["code"] as int;
12 | message = json["message"] as String;
13 | if (json.containsKey("data")) {
14 | data = _generateData(json["data"]);
15 | }
16 | }
17 |
18 | T? _generateData(dynamic json) {
19 | if (json == null) {
20 | return null;
21 | } else if (T.toString() == 'String') {
22 | return json.toString() as T;
23 | } else if (T.toString() == 'Map') {
24 | return json as T;
25 | } else {
26 | return JsonConvert.fromJsonAsT(json);
27 | }
28 | }
29 |
30 | bool isSuccessful() {
31 | return code == 200;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/lib/entity/login_resp_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_field.dart';
2 | import 'package:alist/generated/json/login_resp_entity.g.dart';
3 | import 'dart:convert';
4 |
5 | @JsonSerializable()
6 | class LoginRespEntity {
7 | late String token;
8 |
9 | LoginRespEntity();
10 |
11 | factory LoginRespEntity.fromJson(Map json) => $LoginRespEntityFromJson(json);
12 |
13 | Map toJson() => $LoginRespEntityToJson(this);
14 |
15 | @override
16 | String toString() {
17 | return jsonEncode(this);
18 | }
19 | }
--------------------------------------------------------------------------------
/lib/entity/mkdir_req.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_field.dart';
2 | import 'package:alist/generated/json/mkdir_req.g.dart';
3 | import 'dart:convert';
4 |
5 | @JsonSerializable()
6 | class MkdirReq {
7 | late String path;
8 |
9 | MkdirReq();
10 |
11 | factory MkdirReq.fromJson(Map json) => $MkdirReqFromJson(json);
12 |
13 | Map toJson() => $MkdirReqToJson(this);
14 |
15 | @override
16 | String toString() {
17 | return jsonEncode(this);
18 | }
19 | }
--------------------------------------------------------------------------------
/lib/entity/my_info_resp.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_field.dart';
2 | import 'package:alist/generated/json/my_info_resp.g.dart';
3 | import 'dart:convert';
4 |
5 | @JsonSerializable()
6 | class MyInfoResp {
7 | late int id;
8 | late String username;
9 | late String password;
10 | @JSONField(name: "base_path")
11 | String basePath = "";
12 | int role = 0;
13 | bool disabled = false;
14 | int permission = -1;
15 | @JSONField(name: "sso_id")
16 | String ssoId = "";
17 | bool otp = false;
18 |
19 | MyInfoResp();
20 |
21 | factory MyInfoResp.fromJson(Map json) => $MyInfoRespFromJson(json);
22 |
23 | Map toJson() => $MyInfoRespToJson(this);
24 |
25 | @override
26 | String toString() {
27 | return jsonEncode(this);
28 | }
29 | }
--------------------------------------------------------------------------------
/lib/entity/player_resolve_info_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_field.dart';
2 | import 'package:alist/generated/json/player_resolve_info_entity.g.dart';
3 | import 'dart:convert';
4 | export 'package:alist/generated/json/player_resolve_info_entity.g.dart';
5 |
6 | @JsonSerializable()
7 | class ExternalPlayerEntity {
8 | late String packageName;
9 | late String activity;
10 | late String label;
11 | late String icon;
12 |
13 | ExternalPlayerEntity();
14 |
15 | factory ExternalPlayerEntity.fromJson(Map json) => $ExternalPlayerEntityFromJson(json);
16 |
17 | Map toJson() => $ExternalPlayerEntityToJson(this);
18 |
19 | @override
20 | String toString() {
21 | return jsonEncode(this);
22 | }
23 | }
--------------------------------------------------------------------------------
/lib/entity/public_settings_resp.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_field.dart';
2 | import 'package:alist/generated/json/public_settings_resp.g.dart';
3 | import 'dart:convert';
4 | export 'package:alist/generated/json/public_settings_resp.g.dart';
5 |
6 | @JsonSerializable()
7 | class PublicSettingsResp {
8 | @JSONField(name: "allow_indexed")
9 | String? allowIndexed;
10 | @JSONField(name: "allow_mounted")
11 | String? allowMounted;
12 | String? announcement;
13 | @JSONField(name: "audio_autoplay")
14 | String? audioAutoplay;
15 | @JSONField(name: "audio_cover")
16 | String? audioCover;
17 | @JSONField(name: "auto_update_index")
18 | String? autoUpdateIndex;
19 | @JSONField(name: "default_page_size")
20 | String? defaultPageSize;
21 | @JSONField(name: "external_previews")
22 | String? externalPreviews;
23 | String? favicon;
24 | @JSONField(name: "filename_char_mapping")
25 | String? filenameCharMapping;
26 | @JSONField(name: "forward_direct_link_params")
27 | String? forwardDirectLinkParams;
28 | @JSONField(name: "hide_files")
29 | String? hideFiles;
30 | @JSONField(name: "home_container")
31 | String? homeContainer;
32 | @JSONField(name: "home_icon")
33 | String? homeIcon;
34 | @JSONField(name: "iframe_previews")
35 | String? iframePreviews;
36 | String? logo;
37 | @JSONField(name: "main_color")
38 | String? mainColor;
39 | @JSONField(name: "ocr_api")
40 | String? ocrApi;
41 | @JSONField(name: "package_download")
42 | String? packageDownload;
43 | @JSONField(name: "pagination_type")
44 | String? paginationType;
45 | @JSONField(name: "robots_txt")
46 | String? robotsTxt;
47 | @JSONField(name: "search_index")
48 | String? searchIndex;
49 | @JSONField(name: "settings_layout")
50 | String? settingsLayout;
51 | @JSONField(name: "site_title")
52 | String? siteTitle;
53 | @JSONField(name: "sso_login_enabled")
54 | String? ssoLoginEnabled;
55 | @JSONField(name: "sso_login_platform")
56 | String? ssoLoginPlatform;
57 | String? version;
58 | @JSONField(name: "video_autoplay")
59 | String? videoAutoplay;
60 |
61 | PublicSettingsResp();
62 |
63 | factory PublicSettingsResp.fromJson(Map json) => $PublicSettingsRespFromJson(json);
64 |
65 | Map toJson() => $PublicSettingsRespToJson(this);
66 |
67 | @override
68 | String toString() {
69 | return jsonEncode(this);
70 | }
71 | }
--------------------------------------------------------------------------------
/lib/generated/color_schemes.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | const lightColorScheme = ColorScheme(
4 | brightness: Brightness.light,
5 | primary: Color(0xFF0060A9),
6 | onPrimary: Color(0xFFFFFFFF),
7 | primaryContainer: Color(0xFFD3E4FF),
8 | onPrimaryContainer: Color(0xFF001C38),
9 | secondary: Color(0xFF006A64),
10 | onSecondary: Color(0xFFFFFFFF),
11 | secondaryContainer: Color(0xFF71F7EC),
12 | onSecondaryContainer: Color(0xFF00201E),
13 | tertiary: Color(0xFF6C5677),
14 | onTertiary: Color(0xFFFFFFFF),
15 | tertiaryContainer: Color(0xFFF5D9FF),
16 | onTertiaryContainer: Color(0xFF261431),
17 | error: Color(0xFFBA1A1A),
18 | errorContainer: Color(0xFFFFDAD6),
19 | onError: Color(0xFFFFFFFF),
20 | onErrorContainer: Color(0xFF410002),
21 | background: Color(0xFFFDFCFF),
22 | onBackground: Color(0xFF1A1C1E),
23 | surface: Color(0xFFFDFCFF),
24 | onSurface: Color(0xFF1A1C1E),
25 | surfaceVariant: Color(0xFFDFE2EB),
26 | onSurfaceVariant: Color(0xFF43474E),
27 | outline: Color(0xFF73777F),
28 | onInverseSurface: Color(0xFFF1F0F4),
29 | inverseSurface: Color(0xFF2F3033),
30 | inversePrimary: Color(0xFFA2C9FF),
31 | shadow: Color(0xFF000000),
32 | surfaceTint: Color(0xFF0060A9),
33 | outlineVariant: Color(0xFFC3C6CF),
34 | scrim: Color(0xFF000000),
35 | );
36 |
37 | const darkColorScheme = ColorScheme(
38 | brightness: Brightness.dark,
39 | primary: Color(0xFFA2C9FF),
40 | onPrimary: Color(0xFF00315B),
41 | primaryContainer: Color(0xFF004881),
42 | onPrimaryContainer: Color(0xFFD3E4FF),
43 | secondary: Color(0xFF50DBD0),
44 | onSecondary: Color(0xFF003734),
45 | secondaryContainer: Color(0xFF00504B),
46 | onSecondaryContainer: Color(0xFF71F7EC),
47 | tertiary: Color(0xFFD8BDE3),
48 | onTertiary: Color(0xFF3C2947),
49 | tertiaryContainer: Color(0xFF533F5E),
50 | onTertiaryContainer: Color(0xFFF5D9FF),
51 | error: Color(0xFFFFB4AB),
52 | errorContainer: Color(0xFF93000A),
53 | onError: Color(0xFF690005),
54 | onErrorContainer: Color(0xFFFFDAD6),
55 | background: Color(0xFF111111),
56 | onBackground: Color(0xFFE3E2E6),
57 | surface: Color(0xFF111111),
58 | onSurface: Color(0xFFE3E2E6),
59 | surfaceVariant: Color(0xFF43474E),
60 | onSurfaceVariant: Color(0xFFC3C6CF),
61 | outline: Color(0xFF8D9199),
62 | onInverseSurface: Color(0xFF111111),
63 | inverseSurface: Color(0xFFE3E2E6),
64 | inversePrimary: Color(0xFF0060A9),
65 | shadow: Color(0xFF000000),
66 | surfaceTint: Color(0xFFA2C9FF),
67 | outlineVariant: Color(0xFF43474E),
68 | scrim: Color(0xFF000000),
69 | );
70 |
--------------------------------------------------------------------------------
/lib/generated/images.dart:
--------------------------------------------------------------------------------
1 | class Images {
2 | static const String accountIcon = 'assets/images/account_icon.png';
3 | static const String accountIconChoosed = 'assets/images/account_icon_choosed.png';
4 | static const String fileTypeApk = 'assets/images/file_type_apk.png';
5 | static const String fileTypeAudio = 'assets/images/file_type_audio.png';
6 | static const String fileTypeCode = 'assets/images/file_type_code.png';
7 | static const String fileTypeDocment = 'assets/images/file_type_docment.png';
8 | static const String fileTypeExcel = 'assets/images/file_type_excel.png';
9 | static const String fileTypeFolder = 'assets/images/file_type_folder.png';
10 | static const String fileTypeImage = 'assets/images/file_type_image.png';
11 | static const String fileTypeMd = 'assets/images/file_type_md.png';
12 | static const String fileTypePdf = 'assets/images/file_type_pdf.png';
13 | static const String fileTypePpt = 'assets/images/file_type_ppt.png';
14 | static const String fileTypeUnknow = 'assets/images/file_type_unknow.png';
15 | static const String fileTypeVideo = 'assets/images/file_type_video.png';
16 | static const String fileTypeWord = 'assets/images/file_type_word.png';
17 | static const String fileTypeZip = 'assets/images/file_type_zip.png';
18 | static const String icInfuse = 'assets/images/ic_infuse.png';
19 | static const String icLauncher = 'assets/images/ic_launcher.png';
20 | static const String icNplayer = 'assets/images/ic_nplayer.png';
21 | static const String icVlc = 'assets/images/ic_vlc.png';
22 | static const String iconArrowRight = 'assets/images/icon_arrow_right.png';
23 | static const String iconFfwd = 'assets/images/icon_ffwd.png';
24 | static const String loginScreenAccount = 'assets/images/login_screen_account.png';
25 | static const String loginScreenPassword = 'assets/images/login_screen_password.png';
26 | static const String loginScreenServerUrl = 'assets/images/login_screen_server_url.png';
27 | static const String logo = 'assets/images/logo.png';
28 | static const String settingsScreenAbout = 'assets/images/settings_screen_about.png';
29 | static const String settingsScreenAccount = 'assets/images/settings_screen_account.png';
30 | static const String settingsScreenCacheManager = 'assets/images/settings_screen_cache_manager.png';
31 | static const String settingsScreenDonate = 'assets/images/settings_screen_donate.png';
32 | static const String settingsScreenDownload = 'assets/images/settings_screen_download.png';
33 | static const String settingsScreenPlayer = 'assets/images/settings_screen_player.png';
34 | static const String settingsScreenPrivacyPolicy = 'assets/images/settings_screen_privacy_policy.png';
35 | }
36 |
--------------------------------------------------------------------------------
/lib/generated/json/base/json_field.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: non_constant_identifier_names
2 | // ignore_for_file: camel_case_types
3 | // ignore_for_file: prefer_single_quotes
4 |
5 | // This file is automatically generated. DO NOT EDIT, all your changes would be lost.
6 |
7 | import 'package:meta/meta_meta.dart';
8 |
9 | @Target({TargetKind.classType})
10 | class JsonSerializable {
11 | const JsonSerializable();
12 | }
13 |
14 | @Target({TargetKind.field})
15 | class JSONField {
16 | //Specify the parse field name
17 | final String? name;
18 |
19 | //Whether to participate in toJson
20 | final bool? serialize;
21 |
22 | //Whether to participate in fromMap
23 | final bool? deserialize;
24 |
25 | //Whether to participate in copyWith
26 | final bool? copyWith;
27 |
28 | //Enumeration or not
29 | final bool? isEnum;
30 |
31 | const JSONField({this.name, this.serialize, this.deserialize, this.isEnum, this.copyWith});
32 | }
33 |
--------------------------------------------------------------------------------
/lib/generated/json/copy_move_req.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_convert_content.dart';
2 | import 'package:alist/entity/copy_move_req.dart';
3 |
4 | CopyMoveReq $CopyMoveReqFromJson(Map json) {
5 | final CopyMoveReq copyMoveReq = CopyMoveReq();
6 | final String? srcDir = jsonConvert.convert(json['src_dir']);
7 | if (srcDir != null) {
8 | copyMoveReq.srcDir = srcDir;
9 | }
10 | final String? dstDir = jsonConvert.convert(json['dst_dir']);
11 | if (dstDir != null) {
12 | copyMoveReq.dstDir = dstDir;
13 | }
14 | final List? names = (json['names'] as List?)?.map(
15 | (e) => jsonConvert.convert(e) as String).toList();
16 | if (names != null) {
17 | copyMoveReq.names = names;
18 | }
19 | return copyMoveReq;
20 | }
21 |
22 | Map $CopyMoveReqToJson(CopyMoveReq entity) {
23 | final Map data = {};
24 | data['src_dir'] = entity.srcDir;
25 | data['dst_dir'] = entity.dstDir;
26 | data['names'] = entity.names;
27 | return data;
28 | }
29 |
30 | extension CopyMoveReqExtension on CopyMoveReq {
31 | CopyMoveReq copyWith({
32 | String? srcDir,
33 | String? dstDir,
34 | List? names,
35 | }) {
36 | return CopyMoveReq()
37 | ..srcDir = srcDir ?? this.srcDir
38 | ..dstDir = dstDir ?? this.dstDir
39 | ..names = names ?? this.names;
40 | }
41 | }
--------------------------------------------------------------------------------
/lib/generated/json/donate_config_entity.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_convert_content.dart';
2 | import 'package:alist/entity/donate_config_entity.dart';
3 |
4 | DonateConfigEntity $DonateConfigEntityFromJson(Map json) {
5 | final DonateConfigEntity donateConfigEntity = DonateConfigEntity();
6 | final String? wechat = jsonConvert.convert(json['wechat']);
7 | if (wechat != null) {
8 | donateConfigEntity.wechat = wechat;
9 | }
10 | final String? wechatSmall = jsonConvert.convert(json['wechat_small']);
11 | if (wechatSmall != null) {
12 | donateConfigEntity.wechatSmall = wechatSmall;
13 | }
14 | final String? alipay = jsonConvert.convert(json['alipay']);
15 | if (alipay != null) {
16 | donateConfigEntity.alipay = alipay;
17 | }
18 | final String? alipaySmall = jsonConvert.convert(json['alipay_small']);
19 | if (alipaySmall != null) {
20 | donateConfigEntity.alipaySmall = alipaySmall;
21 | }
22 | return donateConfigEntity;
23 | }
24 |
25 | Map $DonateConfigEntityToJson(DonateConfigEntity entity) {
26 | final Map data = {};
27 | data['wechat'] = entity.wechat;
28 | data['wechat_small'] = entity.wechatSmall;
29 | data['alipay'] = entity.alipay;
30 | data['alipay_small'] = entity.alipaySmall;
31 | return data;
32 | }
33 |
34 | extension DonateConfigEntityExtension on DonateConfigEntity {
35 | DonateConfigEntity copyWith({
36 | String? wechat,
37 | String? wechatSmall,
38 | String? alipay,
39 | String? alipaySmall,
40 | }) {
41 | return DonateConfigEntity()
42 | ..wechat = wechat ?? this.wechat
43 | ..wechatSmall = wechatSmall ?? this.wechatSmall
44 | ..alipay = alipay ?? this.alipay
45 | ..alipaySmall = alipaySmall ?? this.alipaySmall;
46 | }
47 | }
--------------------------------------------------------------------------------
/lib/generated/json/downloads_info.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_convert_content.dart';
2 | import 'package:alist/entity/downloads_info.dart';
3 |
4 | DownloadsInfo $DownloadsInfoFromJson(Map json) {
5 | final DownloadsInfo downloadsInfo = DownloadsInfo();
6 | final bool? isSupportRange = jsonConvert.convert(
7 | json['isSupportRange']);
8 | if (isSupportRange != null) {
9 | downloadsInfo.isSupportRange = isSupportRange;
10 | }
11 | final bool? decompress = jsonConvert.convert(json['decompress']);
12 | if (decompress != null) {
13 | downloadsInfo.decompress = decompress;
14 | }
15 | final String? lastModified = jsonConvert.convert(
16 | json['lastModified']);
17 | if (lastModified != null) {
18 | downloadsInfo.lastModified = lastModified;
19 | }
20 | final String? etag = jsonConvert.convert(json['etag']);
21 | if (etag != null) {
22 | downloadsInfo.etag = etag;
23 | }
24 | final int? contentLength = jsonConvert.convert(json['contentLength']);
25 | if (contentLength != null) {
26 | downloadsInfo.contentLength = contentLength;
27 | }
28 | return downloadsInfo;
29 | }
30 |
31 | Map $DownloadsInfoToJson(DownloadsInfo entity) {
32 | final Map data = {};
33 | data['isSupportRange'] = entity.isSupportRange;
34 | data['decompress'] = entity.decompress;
35 | data['lastModified'] = entity.lastModified;
36 | data['etag'] = entity.etag;
37 | data['contentLength'] = entity.contentLength;
38 | return data;
39 | }
40 |
41 | extension DownloadsInfoExtension on DownloadsInfo {
42 | DownloadsInfo copyWith({
43 | bool? isSupportRange,
44 | bool? decompress,
45 | String? lastModified,
46 | String? etag,
47 | int? contentLength,
48 | }) {
49 | return DownloadsInfo()
50 | ..isSupportRange = isSupportRange ?? this.isSupportRange
51 | ..decompress = decompress ?? this.decompress
52 | ..lastModified = lastModified ?? this.lastModified
53 | ..etag = etag ?? this.etag
54 | ..contentLength = contentLength ?? this.contentLength;
55 | }
56 | }
--------------------------------------------------------------------------------
/lib/generated/json/file_remove_req.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_convert_content.dart';
2 | import 'package:alist/entity/file_remove_req.dart';
3 |
4 | FileRemoveReq $FileRemoveReqFromJson(Map json) {
5 | final FileRemoveReq fileRemoveReq = FileRemoveReq();
6 | final String? dir = jsonConvert.convert(json['dir']);
7 | if (dir != null) {
8 | fileRemoveReq.dir = dir;
9 | }
10 | final List? names = (json['names'] as List?)?.map(
11 | (e) => jsonConvert.convert(e) as String).toList();
12 | if (names != null) {
13 | fileRemoveReq.names = names;
14 | }
15 | return fileRemoveReq;
16 | }
17 |
18 | Map $FileRemoveReqToJson(FileRemoveReq entity) {
19 | final Map data = {};
20 | data['dir'] = entity.dir;
21 | data['names'] = entity.names;
22 | return data;
23 | }
24 |
25 | extension FileRemoveReqExtension on FileRemoveReq {
26 | FileRemoveReq copyWith({
27 | String? dir,
28 | List? names,
29 | }) {
30 | return FileRemoveReq()
31 | ..dir = dir ?? this.dir
32 | ..names = names ?? this.names;
33 | }
34 | }
--------------------------------------------------------------------------------
/lib/generated/json/file_rename_req.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_convert_content.dart';
2 | import 'package:alist/entity/file_rename_req.dart';
3 |
4 | FileRenameReq $FileRenameReqFromJson(Map json) {
5 | final FileRenameReq fileRenameReq = FileRenameReq();
6 | final String? path = jsonConvert.convert(json['path']);
7 | if (path != null) {
8 | fileRenameReq.path = path;
9 | }
10 | final String? name = jsonConvert.convert(json['name']);
11 | if (name != null) {
12 | fileRenameReq.name = name;
13 | }
14 | return fileRenameReq;
15 | }
16 |
17 | Map $FileRenameReqToJson(FileRenameReq entity) {
18 | final Map data = {};
19 | data['path'] = entity.path;
20 | data['name'] = entity.name;
21 | return data;
22 | }
23 |
24 | extension FileRenameReqExtension on FileRenameReq {
25 | FileRenameReq copyWith({
26 | String? path,
27 | String? name,
28 | }) {
29 | return FileRenameReq()
30 | ..path = path ?? this.path
31 | ..name = name ?? this.name;
32 | }
33 | }
--------------------------------------------------------------------------------
/lib/generated/json/login_resp_entity.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_convert_content.dart';
2 | import 'package:alist/entity/login_resp_entity.dart';
3 |
4 | LoginRespEntity $LoginRespEntityFromJson(Map json) {
5 | final LoginRespEntity loginRespEntity = LoginRespEntity();
6 | final String? token = jsonConvert.convert(json['token']);
7 | if (token != null) {
8 | loginRespEntity.token = token;
9 | }
10 | return loginRespEntity;
11 | }
12 |
13 | Map $LoginRespEntityToJson(LoginRespEntity entity) {
14 | final Map data = {};
15 | data['token'] = entity.token;
16 | return data;
17 | }
18 |
19 | extension LoginRespEntityExtension on LoginRespEntity {
20 | LoginRespEntity copyWith({
21 | String? token,
22 | }) {
23 | return LoginRespEntity()
24 | ..token = token ?? this.token;
25 | }
26 | }
--------------------------------------------------------------------------------
/lib/generated/json/mkdir_req.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_convert_content.dart';
2 | import 'package:alist/entity/mkdir_req.dart';
3 |
4 | MkdirReq $MkdirReqFromJson(Map json) {
5 | final MkdirReq mkdirReq = MkdirReq();
6 | final String? path = jsonConvert.convert(json['path']);
7 | if (path != null) {
8 | mkdirReq.path = path;
9 | }
10 | return mkdirReq;
11 | }
12 |
13 | Map $MkdirReqToJson(MkdirReq entity) {
14 | final Map data = {};
15 | data['path'] = entity.path;
16 | return data;
17 | }
18 |
19 | extension MkdirReqExtension on MkdirReq {
20 | MkdirReq copyWith({
21 | String? path,
22 | }) {
23 | return MkdirReq()
24 | ..path = path ?? this.path;
25 | }
26 | }
--------------------------------------------------------------------------------
/lib/generated/json/my_info_resp.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_convert_content.dart';
2 | import 'package:alist/entity/my_info_resp.dart';
3 |
4 | MyInfoResp $MyInfoRespFromJson(Map json) {
5 | final MyInfoResp myInfoResp = MyInfoResp();
6 | final int? id = jsonConvert.convert(json['id']);
7 | if (id != null) {
8 | myInfoResp.id = id;
9 | }
10 | final String? username = jsonConvert.convert(json['username']);
11 | if (username != null) {
12 | myInfoResp.username = username;
13 | }
14 | final String? password = jsonConvert.convert(json['password']);
15 | if (password != null) {
16 | myInfoResp.password = password;
17 | }
18 | final String? basePath = jsonConvert.convert(json['base_path']);
19 | if (basePath != null) {
20 | myInfoResp.basePath = basePath;
21 | }
22 | final int? role = jsonConvert.convert(json['role']);
23 | if (role != null) {
24 | myInfoResp.role = role;
25 | }
26 | final bool? disabled = jsonConvert.convert(json['disabled']);
27 | if (disabled != null) {
28 | myInfoResp.disabled = disabled;
29 | }
30 | final int? permission = jsonConvert.convert(json['permission']);
31 | if (permission != null) {
32 | myInfoResp.permission = permission;
33 | }
34 | final String? ssoId = jsonConvert.convert(json['sso_id']);
35 | if (ssoId != null) {
36 | myInfoResp.ssoId = ssoId;
37 | }
38 | final bool? otp = jsonConvert.convert(json['otp']);
39 | if (otp != null) {
40 | myInfoResp.otp = otp;
41 | }
42 | return myInfoResp;
43 | }
44 |
45 | Map $MyInfoRespToJson(MyInfoResp entity) {
46 | final Map data = {};
47 | data['id'] = entity.id;
48 | data['username'] = entity.username;
49 | data['password'] = entity.password;
50 | data['base_path'] = entity.basePath;
51 | data['role'] = entity.role;
52 | data['disabled'] = entity.disabled;
53 | data['permission'] = entity.permission;
54 | data['sso_id'] = entity.ssoId;
55 | data['otp'] = entity.otp;
56 | return data;
57 | }
58 |
59 | extension MyInfoRespExtension on MyInfoResp {
60 | MyInfoResp copyWith({
61 | int? id,
62 | String? username,
63 | String? password,
64 | String? basePath,
65 | int? role,
66 | bool? disabled,
67 | int? permission,
68 | String? ssoId,
69 | bool? otp,
70 | }) {
71 | return MyInfoResp()
72 | ..id = id ?? this.id
73 | ..username = username ?? this.username
74 | ..password = password ?? this.password
75 | ..basePath = basePath ?? this.basePath
76 | ..role = role ?? this.role
77 | ..disabled = disabled ?? this.disabled
78 | ..permission = permission ?? this.permission
79 | ..ssoId = ssoId ?? this.ssoId
80 | ..otp = otp ?? this.otp;
81 | }
82 | }
--------------------------------------------------------------------------------
/lib/generated/json/player_resolve_info_entity.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_convert_content.dart';
2 | import 'package:alist/entity/player_resolve_info_entity.dart';
3 |
4 | ExternalPlayerEntity $ExternalPlayerEntityFromJson(Map json) {
5 | final ExternalPlayerEntity externalPlayerEntity = ExternalPlayerEntity();
6 | final String? packageName = jsonConvert.convert(json['packageName']);
7 | if (packageName != null) {
8 | externalPlayerEntity.packageName = packageName;
9 | }
10 | final String? activity = jsonConvert.convert(json['activity']);
11 | if (activity != null) {
12 | externalPlayerEntity.activity = activity;
13 | }
14 | final String? label = jsonConvert.convert(json['label']);
15 | if (label != null) {
16 | externalPlayerEntity.label = label;
17 | }
18 | final String? icon = jsonConvert.convert(json['icon']);
19 | if (icon != null) {
20 | externalPlayerEntity.icon = icon;
21 | }
22 | return externalPlayerEntity;
23 | }
24 |
25 | Map $ExternalPlayerEntityToJson(ExternalPlayerEntity entity) {
26 | final Map data = {};
27 | data['packageName'] = entity.packageName;
28 | data['activity'] = entity.activity;
29 | data['label'] = entity.label;
30 | data['icon'] = entity.icon;
31 | return data;
32 | }
33 |
34 | extension ExternalPlayerEntityExtension on ExternalPlayerEntity {
35 | ExternalPlayerEntity copyWith({
36 | String? packageName,
37 | String? activity,
38 | String? label,
39 | String? icon,
40 | }) {
41 | return ExternalPlayerEntity()
42 | ..packageName = packageName ?? this.packageName
43 | ..activity = activity ?? this.activity
44 | ..label = label ?? this.label
45 | ..icon = icon ?? this.icon;
46 | }
47 | }
--------------------------------------------------------------------------------
/lib/l10n/alist_translations.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/l10n/intl_zh_cn.dart';
2 | import 'package:get/get.dart';
3 |
4 | import 'intl_en_us.dart';
5 |
6 | class AlistTranslations extends Translations {
7 | @override
8 | Map> get keys => {
9 | 'zh_CN': translationsZhCN,
10 | 'en_US': translationsEnUS,
11 | };
12 | }
13 |
--------------------------------------------------------------------------------
/lib/net/base_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/json/base/json_convert_content.dart';
2 | import 'package:alist/util/constant.dart';
3 |
4 | class BaseEntity {
5 |
6 | BaseEntity(this.code, this.message, this.data);
7 |
8 | BaseEntity.fromJson(Map json) {
9 | code = json[AlistConstant.code] as int;
10 | message = json[AlistConstant.message] as String;
11 | if (json.containsKey(AlistConstant.data)) {
12 | data = _generateOBJ(json[AlistConstant.data] as Object?);
13 | }
14 | }
15 |
16 | late int code;
17 | late String message;
18 | T? data;
19 |
20 | T? _generateOBJ(Object? json) {
21 | if (json == null) {
22 | return null;
23 | }
24 | if (T.toString() == 'String') {
25 | return json.toString() as T;
26 | } else if (T.toString() == 'Map') {
27 | return json as T;
28 | } else {
29 | /// List类型数据由fromJsonAsT判断处理
30 | return JsonConvert.fromJsonAsT(json);
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/lib/net/intercept.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/util/constant.dart';
2 | import 'package:alist/util/log_utils.dart';
3 | import 'package:dio/dio.dart';
4 | import 'package:sp_util/sp_util.dart';
5 |
6 | class AuthInterceptor extends Interceptor {
7 | @override
8 | void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
9 | if (options.headers[AlistConstant.noAuth] == 1) {
10 | options.headers.remove(AlistConstant.noAuth);
11 | super.onRequest(options, handler);
12 | return;
13 | }
14 |
15 | final String accessToken = SpUtil.getString(AlistConstant.token) ?? "";
16 | final String serverUrl = SpUtil.getString(AlistConstant.serverUrl) ?? "";
17 | final String url = options.uri.toString();
18 | if (accessToken.isNotEmpty &&
19 | serverUrl.isNotEmpty &&
20 | url.startsWith(serverUrl)) {
21 | options.headers['Authorization'] = accessToken;
22 | }
23 | super.onRequest(options, handler);
24 | }
25 | }
26 |
27 | class LoggingInterceptor extends Interceptor {
28 | late DateTime _startTime;
29 | late DateTime _endTime;
30 |
31 | @override
32 | void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
33 | _startTime = DateTime.now();
34 | Log.d('----------Start----------');
35 | if (options.queryParameters.isEmpty) {
36 | if (options.path.startsWith("http://") ||
37 | options.path.startsWith("https://")) {
38 | Log.d('RequestUrl: ${options.path}');
39 | } else {
40 | Log.d('RequestUrl: ${options.baseUrl}${options.path}');
41 | }
42 | } else {
43 | if (options.path.startsWith("http://") ||
44 | options.path.startsWith("https://")) {
45 | Log.d(
46 | 'RequestUrl: ${options.path}?${Transformer.urlEncodeMap(options.queryParameters)}');
47 | } else {
48 | Log.d(
49 | 'RequestUrl: ${options.baseUrl}${options.path}?${Transformer.urlEncodeMap(options.queryParameters)}');
50 | }
51 | }
52 | Log.d('RequestMethod: ${options.method}');
53 | Log.d('RequestHeaders:${options.headers}');
54 | Log.d('RequestContentType: ${options.contentType}');
55 | Log.d('RequestData: ${options.data}');
56 | super.onRequest(options, handler);
57 | }
58 |
59 | @override
60 | void onResponse(
61 | Response response, ResponseInterceptorHandler handler) {
62 | _endTime = DateTime.now();
63 | final int duration = _endTime.difference(_startTime).inMilliseconds;
64 | Log.d('ResponseCode: ${response.statusCode}');
65 | // 输出结果
66 | Log.json(response.data.toString());
67 | Log.d('----------End: $duration 毫秒----------');
68 | super.onResponse(response, handler);
69 | }
70 |
71 | @override
72 | void onError(DioError err, ErrorInterceptorHandler handler) {
73 | Log.d('----------Error-----------');
74 | super.onError(err, handler);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/lib/net/json_parse_error.dart:
--------------------------------------------------------------------------------
1 | class JsonParseException implements Exception {
2 | final String message;
3 |
4 | JsonParseException(this.message);
5 |
6 | @override
7 | String toString() {
8 | String report = "Error: $message";
9 | return report;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/lib/net/net.dart:
--------------------------------------------------------------------------------
1 | export 'dio_utils.dart';
2 |
--------------------------------------------------------------------------------
/lib/net/net_error_handler.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:alist/l10n/intl_keys.dart';
4 | import 'package:alist/net/json_parse_error.dart';
5 | import 'package:alist/net/redirect_exception.dart';
6 | import 'package:alist/util/log_utils.dart';
7 | import 'package:dio/dio.dart';
8 | import 'package:flustars/flustars.dart';
9 | import 'package:flutter/widgets.dart';
10 | import 'package:get/get.dart';
11 |
12 | class NetErrorHandler {
13 | static String netErrorToMessage(dynamic error) {
14 | if (error is RedirectException) {
15 | return error.message;
16 | }
17 | if (error is JsonParseException) {
18 | return Intl.net_error_parse_error.tr;
19 | }
20 | if (error is SocketException) {
21 | return Intl.net_error_socket_error.tr;
22 | }
23 | if (error is HttpException) {
24 | return Intl.net_error_http_error.tr;
25 | }
26 | if (error is FormatException) {
27 | return Intl.net_error_parse_error.tr;
28 | }
29 | if (error is DioException) {
30 | if (error.error is HandshakeException) {
31 | return Intl.net_error_certificate_error.tr;
32 | }
33 | Log.d(error.type.toString());
34 | switch (error.type) {
35 | case DioExceptionType.connectionTimeout:
36 | return Intl.net_error_connect_timeout_error.tr;
37 | case DioExceptionType.sendTimeout:
38 | return Intl.net_error_send_timeout_error.tr;
39 | case DioExceptionType.receiveTimeout:
40 | return Intl.net_error_receive_timeout_error.tr;
41 | case DioExceptionType.badCertificate:
42 | return Intl.net_error_certificate_error.tr;
43 | case DioExceptionType.badResponse:
44 | if (error.response?.statusCode != null) {
45 | return "Response ${error.response?.statusCode ?? ""} ${error.response?.statusMessage ?? ""}";
46 | }
47 | return Intl.net_error_net_error.tr;
48 | case DioExceptionType.cancel:
49 | return Intl.net_error_cancel_error.tr;
50 | case DioExceptionType.connectionError:
51 | return Intl.net_error_net_error.tr;
52 | default:
53 | break;
54 | }
55 | }
56 | return Intl.net_error_net_error.tr;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/lib/net/redirect_exception.dart:
--------------------------------------------------------------------------------
1 | class RedirectException implements Exception {
2 | final String message;
3 |
4 | RedirectException(this.message);
5 |
6 | @override
7 | String toString() {
8 | String report = "Location: $message";
9 | return report;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/lib/screen/aboute_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/generated/images.dart';
2 | import 'package:alist/widget/alist_scaffold.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:get/get.dart';
5 | import 'package:package_info_plus/package_info_plus.dart';
6 |
7 | import 'package:alist/l10n/intl_keys.dart';
8 |
9 | class AboutScreen extends StatelessWidget {
10 | const AboutScreen({Key? key}) : super(key: key);
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | return AlistScaffold(
15 | appbarTitle: Text(Intl.screenName_about.tr),
16 | body: const _AboutPageContainer(),
17 | );
18 | }
19 | }
20 |
21 | class _AboutPageContainer extends StatefulWidget {
22 | const _AboutPageContainer({Key? key}) : super(key: key);
23 |
24 | @override
25 | State<_AboutPageContainer> createState() => _AboutPageContainerState();
26 | }
27 |
28 | class _AboutPageContainerState extends State<_AboutPageContainer> {
29 | PackageInfo? packageInfo;
30 |
31 | @override
32 | void initState() {
33 | super.initState();
34 | initPackageInfo();
35 | }
36 |
37 | @override
38 | Widget build(BuildContext context) {
39 | return Center(
40 | child: Column(
41 | children: [
42 | Padding(
43 | padding: const EdgeInsets.only(top: 20),
44 | child: Image.asset(Images.logo),
45 | ),
46 | Padding(
47 | padding: const EdgeInsets.only(top: 8),
48 | child: Text(
49 | Intl.appName.tr,
50 | style: Theme.of(context).textTheme.titleLarge,
51 | ),
52 | ),
53 | Padding(
54 | padding: const EdgeInsets.only(top: 2),
55 | child: Text("v${packageInfo?.version ?? ""}"),
56 | ),
57 | ],
58 | ),
59 | );
60 | }
61 |
62 | initPackageInfo() async {
63 | packageInfo = await PackageInfo.fromPlatform();
64 | setState(() {});
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/lib/screen/file_list/file_list_navigator.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/router.dart';
2 | import 'package:alist/screen/file_list/file_list_screen.dart';
3 | import 'package:alist/widget/alist_will_pop_scope.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:get/get.dart';
6 |
7 | class FileListNavigator extends StatefulWidget {
8 | const FileListNavigator({Key? key, required this.isInFileListStack})
9 | : super(key: key);
10 | final bool isInFileListStack;
11 |
12 | @override
13 | State createState() => _FileListNavigatorState();
14 | }
15 |
16 | class _FileListNavigatorState extends State
17 | with AutomaticKeepAliveClientMixin {
18 | final GlobalKey? _key =
19 | Get.nestedKey(AlistRouter.fileListRouterStackId);
20 |
21 | @override
22 | Widget build(BuildContext context) {
23 | super.build(context);
24 | return AlistWillPopScope(
25 | onWillPop: () async {
26 | if (widget.isInFileListStack &&
27 | _key?.currentState != null &&
28 | _key?.currentState?.canPop() == true) {
29 | _key?.currentState?.pop();
30 | return false;
31 | }
32 | return true;
33 | },
34 | child: Navigator(
35 | key: _key,
36 | onGenerateRoute: (settings) {
37 | dynamic arguments = settings.arguments;
38 | return GetPageRoute(
39 | page: () => FileListScreen(
40 | path: arguments?["path"],
41 | sortBy: arguments?["sortBy"],
42 | sortByUp: arguments?["sortByUp"],
43 | backupPassword: arguments?["backupPassword"],
44 | isRootStack: false,
45 | ),
46 | );
47 | },
48 | ),
49 | );
50 | }
51 |
52 | @override
53 | bool get wantKeepAlive => true;
54 | }
55 |
--------------------------------------------------------------------------------
/lib/screen/file_list/file_rename_dialog.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/l10n/intl_keys.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:get/get.dart';
4 |
5 | class FileRenameDialog extends StatefulWidget {
6 | const FileRenameDialog({
7 | Key? key,
8 | required this.controller,
9 | required this.focusNode,
10 | this.onConfirm,
11 | this.onCancel,
12 | }) : super(key: key);
13 | final TextEditingController controller;
14 | final FocusNode focusNode;
15 | final VoidCallback? onConfirm;
16 | final VoidCallback? onCancel;
17 |
18 | @override
19 | State createState() => _FileRenameDialogState();
20 | }
21 |
22 | class _FileRenameDialogState extends State {
23 | var _showClear = false;
24 | var _hasContent = false;
25 |
26 | @override
27 | void initState() {
28 | super.initState();
29 | widget.controller.addListener(() {
30 | var showClear = widget.controller.text.isNotEmpty;
31 | var hasContent = widget.controller.text.trim().isNotEmpty;
32 | if (_showClear != showClear || _hasContent != hasContent) {
33 | setState(() {
34 | _showClear = showClear;
35 | _hasContent = hasContent;
36 | });
37 | }
38 | });
39 | }
40 |
41 | @override
42 | Widget build(BuildContext context) {
43 | return AlertDialog(
44 | title: Text(Intl.fileRenameDialog_title.tr),
45 | content: TextField(
46 | focusNode: widget.focusNode,
47 | autofocus: true,
48 | controller: widget.controller,
49 | decoration: InputDecoration(
50 | border: const OutlineInputBorder(),
51 | hintText: Intl.fileRenameDialog_hint.tr,
52 | suffixIcon: _showClear
53 | ? IconButton(
54 | onPressed: () => widget.controller.clear(),
55 | icon: const Icon(Icons.close),
56 | )
57 | : null,
58 | isCollapsed: true,
59 | isDense: true,
60 | contentPadding:
61 | const EdgeInsets.symmetric(horizontal: 11, vertical: 12),
62 | ),
63 | ),
64 | actions: [
65 | TextButton(
66 | onPressed: widget.onCancel,
67 | child: Text(Intl.fileRenameDialog_btn_cancel.tr),
68 | ),
69 | TextButton(
70 | onPressed: _hasContent ? widget.onConfirm : null,
71 | child: Text(Intl.fileRenameDialog_btn_ok.tr),
72 | ),
73 | ],
74 | );
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/lib/screen/file_list/mkdir_dialog.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/l10n/intl_keys.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:get/get.dart';
4 |
5 | class MkdirDialog extends StatefulWidget {
6 | const MkdirDialog({
7 | Key? key,
8 | required this.controller,
9 | required this.focusNode,
10 | this.onConfirm,
11 | this.onCancel,
12 | }) : super(key: key);
13 | final TextEditingController controller;
14 | final FocusNode focusNode;
15 | final VoidCallback? onConfirm;
16 | final VoidCallback? onCancel;
17 |
18 | @override
19 | State createState() => _MkdirDialogState();
20 | }
21 |
22 | class _MkdirDialogState extends State {
23 | var _showClear = false;
24 | var _hasContent = false;
25 |
26 | @override
27 | void initState() {
28 | super.initState();
29 | widget.controller.addListener(() {
30 | var showClear = widget.controller.text.isNotEmpty;
31 | var hasContent = widget.controller.text.trim().isNotEmpty;
32 | if (_showClear != showClear || _hasContent != hasContent) {
33 | setState(() {
34 | _showClear = showClear;
35 | _hasContent = hasContent;
36 | });
37 | }
38 | });
39 | }
40 |
41 | @override
42 | Widget build(BuildContext context) {
43 | return AlertDialog(
44 | title: Text(Intl.mkdirDialog_title.tr),
45 | content: TextField(
46 | focusNode: widget.focusNode,
47 | autofocus: true,
48 | controller: widget.controller,
49 | decoration: InputDecoration(
50 | border: const OutlineInputBorder(),
51 | hintText: Intl.mkdirDialog_hint.tr,
52 | suffixIcon: _showClear
53 | ? IconButton(
54 | onPressed: () => widget.controller.clear(),
55 | icon: const Icon(Icons.close),
56 | )
57 | : null,
58 | isCollapsed: true,
59 | isDense: true,
60 | contentPadding:
61 | const EdgeInsets.symmetric(horizontal: 11, vertical: 12),
62 | ),
63 | ),
64 | actions: [
65 | TextButton(
66 | onPressed: widget.onCancel,
67 | child: Text(Intl.mkdirDialog_cancel.tr),
68 | ),
69 | TextButton(
70 | onPressed: _hasContent ? widget.onConfirm : null,
71 | child: Text(Intl.mkdirDialog_ok.tr),
72 | ),
73 | ],
74 | );
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/lib/util/constant.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 |
3 | class AlistConstant {
4 | /// App运行在Release环境时,inProduction为true;当App运行在Debug和Profile环境时,inProduction为false
5 | static const bool inProduction = kReleaseMode;
6 |
7 | static bool isDriverTest = false;
8 | static bool isUnitTest = false;
9 |
10 | static const String appName = "AList Client";
11 | static const String data = 'data';
12 | static const String message = 'message';
13 | static const String code = 'code';
14 | static const String noAuth = 'noAuth';
15 |
16 | static const String serverUrl = 'address';
17 | static const String baseUrl = 'baseUrl';
18 | static const String basePath = 'basePath';
19 | static const String username = 'username';
20 | static const String password = 'password';
21 | static const String token = 'token';
22 | static const String guest = 'guest';
23 | static const String useDemoServer = 'useDemoServer';
24 | static const String isAgreePrivacyPolicy = 'isAgreePrivacyPolicy';
25 | static const String ignoreSSLError = "ignoreSSLError";
26 | static const String ignoreAppVersion = "ignoreAppVersion";
27 | static const String isFirstTimeDownload = "isFirstTimeDownload";
28 | static const String isFirstTimeSaveToLocal = "isFirstTimeSaveToLocal";
29 | static const String maxRunningTaskCount = "maxRunningTaskCount";
30 | static const String fileNameMaxLines = 'fileNameMaxLines';
31 | static const String fileSortWayIndex = 'fileSortWayIndex';
32 | static const String fileSortWayUp = 'fileSortWayUp';
33 | static const String videoPlayerName = 'videoPlayerName';
34 | static const String videoPlayerRouter = 'videoPlayerRouter';
35 | static const String playerType = 'playerType';
36 |
37 | static const String locale = 'locale';
38 | }
39 |
--------------------------------------------------------------------------------
/lib/util/download/download_http_client.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:flustars/flustars.dart';
4 |
5 | class DownloadHttpClient {
6 | final HttpClient _httpClient = HttpClient()..autoUncompress = false;
7 | int _lastLimitRequestTime = 0;
8 | bool _requesting = false;
9 |
10 | DownloadHttpClient();
11 |
12 | // limitFrequency 用于解决部分网盘(如:阿里云盘)存在下载链接请求频率限制的问题
13 | // limitFrequency 为与上一次请求的最小时间隔,单位:秒
14 | Future get(String url,
15 | {Map? headers, int? limitFrequency}) async {
16 | if (limitFrequency == null || limitFrequency < 1) {
17 | return _getInner(url, headers: headers);
18 | }
19 |
20 | int now = DateTime.now().millisecondsSinceEpoch;
21 | if (_requesting || now - _lastLimitRequestTime < limitFrequency * 1000) {
22 | do {
23 | await Future.delayed(const Duration(milliseconds: 200));
24 | now = DateTime.now().millisecondsSinceEpoch;
25 | } while (_requesting || now - _lastLimitRequestTime < limitFrequency);
26 | }
27 |
28 | _requesting = true;
29 | try {
30 | return await _getInner(url, headers: headers);
31 | } finally {
32 | _requesting = false;
33 | _lastLimitRequestTime = DateTime.now().millisecondsSinceEpoch;
34 | }
35 | }
36 |
37 | Future _getInner(String url,
38 | {Map? headers}) async {
39 | HttpClientRequest request =
40 | await _httpClient.openUrl("GET", Uri.parse(url));
41 | headers?.forEach((key, value) {
42 | LogUtil.d("header $key=$value");
43 | request.headers.set(key, value);
44 | });
45 | return request.close();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/lib/util/download/download_task_status.dart:
--------------------------------------------------------------------------------
1 | enum DownloadTaskStatus {
2 | waiting,
3 | downloading,
4 | decompressing,
5 | paused,
6 | failed,
7 | finished,
8 | canceled,
9 | }
10 |
--------------------------------------------------------------------------------
/lib/util/file_password_helper.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/database/dao/file_password_dao.dart';
2 | import 'package:alist/database/table/file_password.dart';
3 | import 'package:alist/util/string_utils.dart';
4 | import 'package:alist/util/user_controller.dart';
5 | import 'package:get/get.dart';
6 |
7 | class FilePasswordHelper {
8 | static final FilePasswordHelper _singleton = FilePasswordHelper._();
9 | late FilePasswordDao _filePasswordDao;
10 |
11 | FilePasswordHelper._();
12 |
13 | factory FilePasswordHelper() {
14 | return _singleton;
15 | }
16 |
17 | void setFilePasswordDao(FilePasswordDao filePasswordDao) {
18 | _filePasswordDao = filePasswordDao;
19 | }
20 |
21 | Future fastFindPassword(String remotePath,
22 | {String? backupPassword}) async {
23 | final userController = Get.find();
24 | final user = userController.user.value;
25 | return await findPasswordByPath(user.serverUrl, user.username, remotePath,
26 | backupPassword: backupPassword);
27 | }
28 |
29 | Future findPasswordByPath(
30 | String serverUrl, String userId, String remotePath,
31 | {String? backupPassword}) async {
32 | var path = remotePath;
33 | if (!path.startsWith("/")) {
34 | path = "/$path";
35 | }
36 | FilePassword? filePassword;
37 | if (backupPassword == null) {
38 | do {
39 | filePassword =
40 | await _filePasswordDao.findPasswordByPath(serverUrl, userId, path);
41 | if (filePassword == null) {
42 | path = path.substringBeforeLast("/")!;
43 | }
44 | } while (filePassword == null && path != "");
45 | } else {
46 | filePassword =
47 | await _filePasswordDao.findPasswordByPath(serverUrl, userId, path);
48 | if (filePassword == null) {
49 | return backupPassword;
50 | }
51 | }
52 | return filePassword?.password;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/lib/util/file_type.dart:
--------------------------------------------------------------------------------
1 | enum FileType {
2 | audio,
3 | code,
4 | compress,
5 | email,
6 | excel,
7 | flash,
8 | html,
9 | image,
10 | keynote,
11 | numbers,
12 | others,
13 | pages,
14 | pdf,
15 | ppt,
16 | psd,
17 | sketch,
18 | txt,
19 | video,
20 | word,
21 | folder,
22 | file,
23 | apk,
24 | markdown
25 | }
26 |
--------------------------------------------------------------------------------
/lib/util/focus_node_utils.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | extension FocusNodeUtils on FocusNode {
4 | FocusNode autoFocus() {
5 | Future.delayed(const Duration(milliseconds: 100), () => requestFocus());
6 | return this;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/lib/util/global.dart:
--------------------------------------------------------------------------------
1 | import 'package:get/get.dart';
2 |
3 | class Global {
4 | static String configServerHost = "c.qianyi605.eu.org";
5 | static String demoServerBaseUrl = "https://qianyi605.eu.org/";
6 | static final fileNameMaxLines = 1.obs;
7 | }
--------------------------------------------------------------------------------
/lib/util/iterator.dart:
--------------------------------------------------------------------------------
1 | extension IteratablEextension on Iterable {
2 | E? firstWhereOrNull(bool Function(E element) test) {
3 | for (E element in this) {
4 | if (test(element)) return element;
5 | }
6 | return null;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/lib/util/keyboard_utils.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class KeyboardUtil {
4 | static void hideKeyboard(BuildContext context) {
5 | FocusScopeNode currentFocus = FocusScope.of(context);
6 | if (!currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) {
7 | FocusManager.instance.primaryFocus!.unfocus();
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/lib/util/markdown_utils.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:alist/util/global.dart';
4 |
5 | class MarkdownUtil {
6 | static makePreviewUrl(String url) {
7 | String scheme;
8 | if (Platform.isIOS && url.startsWith("http://")) {
9 | scheme = "http";
10 | } else {
11 | scheme = "https";
12 | }
13 |
14 | return "$scheme://${Global.configServerHost}/alist_h5/showMarkDown?markdownUrl=${Uri.encodeComponent(url)}";
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/lib/util/named_router.dart:
--------------------------------------------------------------------------------
1 | class NamedRouter {
2 | // root
3 | static const root = "/index";
4 |
5 | // login
6 | static const login = "/login";
7 |
8 | // home index
9 | static const home = "/home";
10 |
11 | // file list
12 | static const fileList = "/fileList";
13 |
14 | // file list
15 | static const settings = "/settings";
16 |
17 | // video player
18 | static const videoPlayer = "/videoPlayer";
19 |
20 | // donate
21 | static const donate = "/donate";
22 |
23 | // donate
24 | static const about = "/about";
25 |
26 | // gallery
27 | static const gallery = "/gallery";
28 |
29 | // audio player
30 | static const audioPlayer = "/audioPlayer";
31 |
32 | // file reader
33 | static const fileReader = "/fileReader";
34 |
35 | // web
36 | static const web = "/web";
37 |
38 | // pdfReader
39 | static const pdfReader = "/pdfReader";
40 |
41 | // uploadingFiles
42 | static const uploadingFiles = "/uploadingFiles";
43 |
44 | // account
45 | static const account = "/account";
46 |
47 | // download manager
48 | static const downloadManager = "/downloadManager";
49 |
50 | // file list search
51 | static const fileSearch = "/fileSearch";
52 |
53 | // cache manager
54 | static const cacheManager = "/cacheManager";
55 |
56 | // player settings
57 | static const playerSettings = "/playerSettings";
58 | }
59 |
--------------------------------------------------------------------------------
/lib/util/nature_sort.dart:
--------------------------------------------------------------------------------
1 | class NaturalSort {
2 | NaturalSort._();
3 |
4 | static int _commonPrefix(String a, String b) {
5 | int m = a.length;
6 | int n = b.length;
7 | if (n < m) {
8 | m = n;
9 | }
10 | if (m == 0) {
11 | return 0;
12 | }
13 |
14 | for (int i = 0; i < m; i++) {
15 | String ca = a[i];
16 | String cb = b[i];
17 | if ((ca.compareTo('0') >= 0 && ca.compareTo('9') <= 0) ||
18 | (cb.compareTo('0') >= 0 && cb.compareTo('9') <= 0) ||
19 | ca != cb) {
20 | return i;
21 | }
22 | }
23 | return m;
24 | }
25 |
26 | static int _digits(String s) {
27 | for (int i = 0; i < s.length; i++) {
28 | String c = s[i];
29 | if (c.compareTo('0') < 0 || c.compareTo('9') > 0) {
30 | return i;
31 | }
32 | }
33 | return s.length;
34 | }
35 |
36 | static int compare(String a, String b) {
37 | if (a == b) {
38 | return 0;
39 | }
40 |
41 | while (true) {
42 | int p = _commonPrefix(a, b);
43 | if (p != 0) {
44 | a = a.substring(p);
45 | b = b.substring(p);
46 | }
47 | if (a.isEmpty) {
48 | return b.isNotEmpty ? -1 : 1;
49 | }
50 | int ia = _digits(a);
51 | if (ia > 0) {
52 | int ib = _digits(b);
53 | if (ib > 0) {
54 | // Both sides have digits.
55 | int an = int.parse(a.substring(0, ia));
56 | int bn = int.parse(b.substring(0, ib));
57 | if (an != bn) {
58 | return an.compareTo(bn);
59 | }
60 | // Semantically the same digits.
61 | if (ia != a.length && ib != b.length) {
62 | a = a.substring(ia);
63 | b = b.substring(ib);
64 | continue;
65 | }
66 | }
67 | }
68 | return a.compareTo(b);
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/lib/util/string_utils.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'dart:convert';
3 | import 'package:crypto/crypto.dart';
4 |
5 | extension StringExtensions on String? {
6 | String? substringAfterLast(String separator) {
7 | if (this == null) {
8 | return null;
9 | }
10 |
11 | final index = this!.lastIndexOf(separator);
12 | if (index == -1) {
13 | return this;
14 | }
15 | return this!.substring(index + separator.length);
16 | }
17 |
18 | String? substringBeforeLast(String separator) {
19 | if (this == null) {
20 | return null;
21 | }
22 |
23 | final index = this!.lastIndexOf(separator);
24 | if (index == -1) {
25 | return this;
26 | }
27 | return this!.substring(0, index);
28 | }
29 |
30 | String md5String(){
31 | var bytes = utf8.encode(this ?? "");
32 | var md5Hash = md5.convert(bytes);
33 | String md5String = md5Hash.toString();
34 | return md5String;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/lib/util/widget_utils.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class WidgetUtils {
4 | static bool isDarkMode(BuildContext context) {
5 | return Theme.of(context).brightness == Brightness.dark;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/lib/widget/alist_checkbox.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 |
3 | class AlistCheckBox extends StatelessWidget {
4 | final bool? value;
5 | final String text;
6 | final ValueChanged? onChanged;
7 |
8 | const AlistCheckBox({
9 | super.key,
10 | required this.value,
11 | required this.text,
12 | required this.onChanged,
13 | });
14 |
15 | @override
16 | Widget build(BuildContext context) {
17 | return Row(
18 | mainAxisSize: MainAxisSize.min,
19 | children: [
20 | CupertinoCheckbox(
21 | value: value,
22 | // materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
23 | onChanged: onChanged,
24 | ),
25 | GestureDetector(
26 | onTap: onChanged == null
27 | ? null
28 | : () {
29 | onChanged!(!(value ?? false));
30 | },
31 | child: Text(text),
32 | ),
33 | ],
34 | );
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/lib/widget/alist_scaffold.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/util/widget_utils.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | class AlistScaffold extends StatelessWidget {
5 | const AlistScaffold({
6 | Key? key,
7 | this.appbarTitle,
8 | required this.body,
9 | this.onLeadingDoubleTap,
10 | this.resizeToAvoidBottomInset,
11 | this.appbarActions,
12 | this.showAppbar = true,
13 | }) : super(key: key);
14 | final Widget? appbarTitle;
15 | final Widget body;
16 | final GestureTapCallback? onLeadingDoubleTap;
17 | final bool? resizeToAvoidBottomInset;
18 | final List? appbarActions;
19 | final bool showAppbar;
20 |
21 | @override
22 | Widget build(BuildContext context) {
23 | List colors = List.empty();
24 | bool isDarkMode = WidgetUtils.isDarkMode(context);
25 |
26 | if (!isDarkMode) {
27 | Color startColor = Theme.of(context).colorScheme.primaryContainer;
28 | const Color endColor = Colors.white;
29 | colors = [startColor, endColor];
30 | }
31 | final ModalRoute? parentRoute = ModalRoute.of(context);
32 | var canPop = null != parentRoute && parentRoute.canPop;
33 |
34 | return DecoratedBox(
35 | decoration: isDarkMode
36 | ? const BoxDecoration()
37 | : BoxDecoration(
38 | gradient: LinearGradient(
39 | colors: colors,
40 | begin: Alignment.topCenter,
41 | end: Alignment.bottomCenter,
42 | ),
43 | ),
44 | child: Scaffold(
45 | backgroundColor: isDarkMode ? null : Colors.transparent,
46 | resizeToAvoidBottomInset: resizeToAvoidBottomInset ?? true,
47 | appBar: !showAppbar
48 | ? null
49 | : AppBar(
50 | leading: canPop
51 | ? GestureDetector(
52 | onDoubleTap: onLeadingDoubleTap,
53 | child: const BackButton(),
54 | )
55 | : null,
56 | automaticallyImplyLeading: false,
57 | backgroundColor: isDarkMode ? null : Colors.transparent,
58 | title: appbarTitle,
59 | actions: appbarActions,
60 | ),
61 | body: SafeArea(child: body),
62 | ));
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/lib/widget/alist_will_pop_scope.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:flutter/material.dart';
4 |
5 | class AlistWillPopScope extends StatelessWidget {
6 | const AlistWillPopScope({
7 | Key? key,
8 | required this.child,
9 | this.onWillPop,
10 | this.alwaysAllowSwipeBackOnIOS = true,
11 | }) : super(key: key);
12 |
13 | final Widget child;
14 | final WillPopCallback? onWillPop;
15 | final bool alwaysAllowSwipeBackOnIOS;
16 |
17 | @override
18 | Widget build(BuildContext context) {
19 | final onWillPop =
20 | (Platform.isIOS && alwaysAllowSwipeBackOnIOS) ? null : this.onWillPop;
21 | return WillPopScope(onWillPop: onWillPop, child: child);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lib/widget/config_file_name_max_lines_dialog.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/l10n/intl_keys.dart';
2 | import 'package:alist/util/constant.dart';
3 | import 'package:alist/util/global.dart';
4 | import 'package:alist/widget/alist_checkbox.dart';
5 | import 'package:flustars/flustars.dart';
6 | import 'package:flutter/material.dart';
7 | import 'package:get/get.dart';
8 |
9 | class ConfigFileNameMaxLinesDialog extends StatelessWidget {
10 | const ConfigFileNameMaxLinesDialog({super.key});
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | return Dialog(
15 | child: Padding(
16 | padding: const EdgeInsets.symmetric(vertical: 15),
17 | child: Column(
18 | crossAxisAlignment: CrossAxisAlignment.start,
19 | mainAxisSize: MainAxisSize.min,
20 | children: [
21 | Center(
22 | child: Text(Intl.configFileNameMaxLinesDialog_title.tr,
23 | style: Theme.of(context).textTheme.titleLarge),
24 | ),
25 | const SizedBox(height: 10),
26 | _buildChoices(),
27 | ],
28 | ),
29 | ),
30 | );
31 | }
32 |
33 | Padding _buildChoices() {
34 | callback(int fileNameMaxLines) {
35 | if (Global.fileNameMaxLines.value != fileNameMaxLines) {
36 | Global.fileNameMaxLines.value = fileNameMaxLines;
37 | SpUtil.putInt(AlistConstant.fileNameMaxLines, fileNameMaxLines);
38 | }
39 | }
40 |
41 | return Padding(
42 | padding: const EdgeInsets.symmetric(horizontal: 20),
43 | child: Obx(() => Column(
44 | crossAxisAlignment: CrossAxisAlignment.start,
45 | mainAxisSize: MainAxisSize.min,
46 | children: [
47 | AlistCheckBox(
48 | value: Global.fileNameMaxLines.value == 1,
49 | text: Intl.configFileNameMaxLinesDialog_choice_one.tr,
50 | onChanged: (bool? b) => callback(1),
51 | ),
52 | AlistCheckBox(
53 | value: Global.fileNameMaxLines.value == 2,
54 | text: Intl.configFileNameMaxLinesDialog_choice_two.tr,
55 | onChanged: (bool? b) => callback(2),
56 | ),
57 | AlistCheckBox(
58 | value: Global.fileNameMaxLines.value > 2,
59 | text: Intl.configFileNameMaxLinesDialog_choice_noLimit.tr,
60 | onChanged: (bool? b) => callback(3),
61 | )
62 | ],
63 | )),
64 | );
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/lib/widget/loading_status_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:alist/l10n/intl_keys.dart';
2 | import 'package:flustars/flustars.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:get/get.dart';
5 |
6 | class LoadingStatusWidget extends StatelessWidget {
7 | const LoadingStatusWidget({
8 | Key? key,
9 | required this.loading,
10 | this.errorMsg,
11 | required this.child,
12 | required this.retryCallback,
13 | }) : super(key: key);
14 | final bool loading;
15 | final String? errorMsg;
16 | final Widget child;
17 | final VoidCallback retryCallback;
18 |
19 | @override
20 | Widget build(BuildContext context) {
21 | if (errorMsg != null && errorMsg!.isNotEmpty) {
22 | return Center(
23 | child: Column(
24 | mainAxisAlignment: MainAxisAlignment.center,
25 | children: [
26 | Padding(
27 | padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
28 | child: Text(errorMsg!),
29 | ),
30 | FilledButton(
31 | onPressed: () {
32 | LogUtil.d("retry...");
33 | retryCallback();
34 | },
35 | child: Text(Intl.loadingStatusWidget_retry.tr),
36 | )
37 | ],
38 | ),
39 | );
40 | } else if (loading) {
41 | return const Center(
42 | child: CircularProgressIndicator(),
43 | );
44 | } else {
45 | return child;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/lib/widget/overflow_text.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class OverflowText extends StatelessWidget {
4 | static const ellipsis = "...";
5 |
6 | const OverflowText({super.key, required this.text, this.style});
7 |
8 | final String text;
9 | final TextStyle? style;
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | return LayoutBuilder(
14 | builder: (BuildContext context, BoxConstraints constraints) {
15 | var textStyle = DefaultTextStyle.of(context).style;
16 | if (style != null) {
17 | textStyle = textStyle.merge(style);
18 | }
19 |
20 | var maxWidth = constraints.biggest.width;
21 |
22 | final textSpan = TextSpan(text: text, style: textStyle);
23 | final textPainter = TextPainter(
24 | text: textSpan,
25 | textDirection: TextDirection.ltr,
26 | )..layout();
27 | if (textPainter.width > maxWidth) {
28 | // LogUtil.d("${textPainter.width} $maxWidth");
29 | var left = 0;
30 | TextSpan? leftText;
31 | var leftWidth = 0.0;
32 | var right = 0;
33 | TextSpan? rightText;
34 | var rightWidth = 0.0;
35 |
36 | var ellipsisText = TextSpan(text: ellipsis, style: textStyle);
37 | textPainter.text = ellipsisText;
38 | textPainter.layout();
39 | maxWidth -= textPainter.width;
40 |
41 | while (leftWidth + rightWidth < maxWidth) {
42 | if (leftWidth <= rightWidth) {
43 | left++;
44 | leftText =
45 | TextSpan(text: text.substring(0, left), style: textStyle);
46 |
47 | textPainter.text = leftText;
48 | textPainter.layout();
49 | leftWidth = textPainter.width;
50 |
51 | if (leftWidth + rightWidth > maxWidth) {
52 | left--;
53 | leftText =
54 | TextSpan(text: text.substring(0, left), style: textStyle);
55 | break;
56 | }
57 | } else {
58 | right++;
59 | rightText = TextSpan(
60 | text: text.substring(text.length - right), style: textStyle);
61 |
62 | textPainter.text = rightText;
63 | textPainter.layout();
64 | rightWidth = textPainter.width;
65 |
66 | if (leftWidth + rightWidth > maxWidth) {
67 | right--;
68 | rightText = TextSpan(
69 | text: text.substring(text.length - right), style: textStyle);
70 | break;
71 | }
72 | }
73 | }
74 |
75 | return Text(
76 | "${leftText?.text ?? ""}$ellipsis${rightText?.text ?? ""}",
77 | style: textStyle,
78 | );
79 | } else {
80 | return Text(text, style: textStyle);
81 | }
82 | });
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/lib/widget/player_selector_dialog.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:alist/entity/player_resolve_info_entity.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
6 |
7 | typedef OnExternalPlayerClick = Function(ExternalPlayerEntity);
8 |
9 | class PlayerSelectorDialog extends StatelessWidget {
10 | const PlayerSelectorDialog(
11 | {super.key,
12 | required this.players,
13 | required this.onPlayerClick});
14 |
15 | final List players;
16 | final OnExternalPlayerClick onPlayerClick;
17 |
18 | @override
19 | Widget build(BuildContext context) {
20 | var itemCount = players.length;
21 |
22 | return Container(
23 | constraints: const BoxConstraints(minHeight: 100, maxHeight: 300),
24 | child: AlignedGridView.count(
25 | crossAxisCount: 4,
26 | shrinkWrap: itemCount < 8,
27 | itemCount: itemCount,
28 | itemBuilder: (context, index) {
29 | var info = players[index];
30 | return GestureDetector(
31 | onTap: () {
32 | onPlayerClick(info);
33 | },
34 | child: _buildPlayerWidget(info.icon, info.label, iconIsFile: info.activity.isNotEmpty),
35 | );
36 | }),
37 | );
38 | }
39 |
40 | Widget _buildPlayerWidget(String icon, String label,
41 | {bool iconIsFile = true}) {
42 | dynamic image = iconIsFile ? FileImage(File(icon)) : AssetImage(icon);
43 |
44 | return Padding(
45 | padding: const EdgeInsets.symmetric(vertical: 10),
46 | child: Column(
47 | mainAxisSize: MainAxisSize.min,
48 | mainAxisAlignment: MainAxisAlignment.center,
49 | children: [
50 | ClipRRect(
51 | borderRadius: BorderRadius.circular(10),
52 | child: Image(
53 | image: image,
54 | width: 45,
55 | height: 45,
56 | ),
57 | ),
58 | Padding(
59 | padding: const EdgeInsets.only(top: 2.0),
60 | child: Text(
61 | label,
62 | textAlign: TextAlign.center,
63 | style: const TextStyle(fontSize: 12),
64 | ),
65 | )
66 | ],
67 | ),
68 | );
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/linux/.gitignore:
--------------------------------------------------------------------------------
1 | flutter/ephemeral
2 |
--------------------------------------------------------------------------------
/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 |
12 | void fl_register_plugins(FlPluginRegistry* registry) {
13 | g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
14 | fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
15 | file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
16 | g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
17 | fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
18 | url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
19 | }
20 |
--------------------------------------------------------------------------------
/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 | file_selector_linux
7 | url_launcher_linux
8 | )
9 |
10 | list(APPEND FLUTTER_FFI_PLUGIN_LIST
11 | )
12 |
13 | set(PLUGIN_BUNDLED_LIBRARIES)
14 |
15 | foreach(plugin ${FLUTTER_PLUGIN_LIST})
16 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
17 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
18 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $)
19 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
20 | endforeach(plugin)
21 |
22 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
23 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
24 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
25 | endforeach(ffi_plugin)
26 |
--------------------------------------------------------------------------------
/linux/main.cc:
--------------------------------------------------------------------------------
1 | #include "my_application.h"
2 |
3 | int main(int argc, char** argv) {
4 | g_autoptr(MyApplication) app = my_application_new();
5 | return g_application_run(G_APPLICATION(app), argc, argv);
6 | }
7 |
--------------------------------------------------------------------------------
/linux/my_application.h:
--------------------------------------------------------------------------------
1 | #ifndef FLUTTER_MY_APPLICATION_H_
2 | #define FLUTTER_MY_APPLICATION_H_
3 |
4 | #include
5 |
6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
7 | GtkApplication)
8 |
9 | /**
10 | * my_application_new:
11 | *
12 | * Creates a new Flutter-based application.
13 | *
14 | * Returns: a new #MyApplication.
15 | */
16 | MyApplication* my_application_new();
17 |
18 | #endif // FLUTTER_MY_APPLICATION_H_
19 |
--------------------------------------------------------------------------------
/macos/.gitignore:
--------------------------------------------------------------------------------
1 | # Flutter-related
2 | **/Flutter/ephemeral/
3 | **/Pods/
4 |
5 | # Xcode-related
6 | **/dgph
7 | **/xcuserdata/
8 |
--------------------------------------------------------------------------------
/macos/Flutter/Flutter-Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "ephemeral/Flutter-Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/macos/Flutter/Flutter-Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "ephemeral/Flutter-Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/macos/Flutter/GeneratedPluginRegistrant.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | import FlutterMacOS
6 | import Foundation
7 |
8 | import audio_service
9 | import audio_session
10 | import device_info_plus
11 | import file_selector_macos
12 | import just_audio
13 | import package_info_plus
14 | import path_provider_foundation
15 | import screen_brightness_macos
16 | import shared_preferences_foundation
17 | import sqflite
18 | import url_launcher_macos
19 | import wakelock_macos
20 |
21 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
22 | AudioServicePlugin.register(with: registry.registrar(forPlugin: "AudioServicePlugin"))
23 | AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
24 | DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
25 | FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
26 | JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin"))
27 | FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
28 | PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
29 | ScreenBrightnessMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenBrightnessMacosPlugin"))
30 | SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
31 | SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
32 | UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
33 | WakelockMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockMacosPlugin"))
34 | }
35 |
--------------------------------------------------------------------------------
/macos/Podfile:
--------------------------------------------------------------------------------
1 | platform :osx, '10.14'
2 |
3 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
4 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
5 |
6 | project 'Runner', {
7 | 'Debug' => :debug,
8 | 'Profile' => :release,
9 | 'Release' => :release,
10 | }
11 |
12 | def flutter_root
13 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
14 | unless File.exist?(generated_xcode_build_settings_path)
15 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
16 | end
17 |
18 | File.foreach(generated_xcode_build_settings_path) do |line|
19 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
20 | return matches[1].strip if matches
21 | end
22 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
23 | end
24 |
25 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
26 |
27 | flutter_macos_podfile_setup
28 |
29 | target 'Runner' do
30 | use_frameworks!
31 | use_modular_headers!
32 |
33 | flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
34 | end
35 |
36 | post_install do |installer|
37 | installer.pods_project.targets.each do |target|
38 | flutter_additional_macos_build_settings(target)
39 | end
40 | end
41 |
--------------------------------------------------------------------------------
/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/macos/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/macos/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | @main
5 | class AppDelegate: FlutterAppDelegate {
6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
7 | return true
8 | }
9 |
10 | override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
11 | return true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/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/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/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 = alist
9 |
10 | // The application's bundle identifier
11 | PRODUCT_BUNDLE_IDENTIFIER = com.github.alist
12 |
13 | // The copyright displayed in application information
14 | PRODUCT_COPYRIGHT = Copyright © 2023 com.github. 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 | com.apple.security.network.client
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/macos/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSMinimumSystemVersion
24 | $(MACOSX_DEPLOYMENT_TARGET)
25 | NSHumanReadableCopyright
26 | $(PRODUCT_COPYRIGHT)
27 | NSMainNibFile
28 | MainMenu
29 | NSPrincipalClass
30 | NSApplication
31 | NSAppTransportSecurity
32 |
33 | NSAllowsArbitraryLoads
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/macos/Runner/MainFlutterWindow.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | class MainFlutterWindow: NSWindow {
5 | override func awakeFromNib() {
6 | let flutterViewController = FlutterViewController.init()
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 | com.apple.security.network.server
8 |
9 | com.apple.security.network.client
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:alist/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 MyApp());
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/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/web/favicon.png
--------------------------------------------------------------------------------
/web/icons/Icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/web/icons/Icon-192.png
--------------------------------------------------------------------------------
/web/icons/Icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/web/icons/Icon-512.png
--------------------------------------------------------------------------------
/web/icons/Icon-maskable-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/web/icons/Icon-maskable-192.png
--------------------------------------------------------------------------------
/web/icons/Icon-maskable-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/web/icons/Icon-maskable-512.png
--------------------------------------------------------------------------------
/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | alist
33 |
34 |
35 |
39 |
40 |
41 |
42 |
43 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/web/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "alist",
3 | "short_name": "alist",
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 |
--------------------------------------------------------------------------------
/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 |
14 | void RegisterPlugins(flutter::PluginRegistry* registry) {
15 | FileSelectorWindowsRegisterWithRegistrar(
16 | registry->GetRegistrarForPlugin("FileSelectorWindows"));
17 | PermissionHandlerWindowsPluginRegisterWithRegistrar(
18 | registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
19 | ScreenBrightnessWindowsPluginRegisterWithRegistrar(
20 | registry->GetRegistrarForPlugin("ScreenBrightnessWindowsPlugin"));
21 | UrlLauncherWindowsRegisterWithRegistrar(
22 | registry->GetRegistrarForPlugin("UrlLauncherWindows"));
23 | }
24 |
--------------------------------------------------------------------------------
/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 | file_selector_windows
7 | permission_handler_windows
8 | screen_brightness_windows
9 | url_launcher_windows
10 | )
11 |
12 | list(APPEND FLUTTER_FFI_PLUGIN_LIST
13 | )
14 |
15 | set(PLUGIN_BUNDLED_LIBRARIES)
16 |
17 | foreach(plugin ${FLUTTER_PLUGIN_LIST})
18 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
19 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
20 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $)
21 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
22 | endforeach(plugin)
23 |
24 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
25 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
26 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
27 | endforeach(ffi_plugin)
28 |
--------------------------------------------------------------------------------
/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/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 | return true;
35 | }
36 |
37 | void FlutterWindow::OnDestroy() {
38 | if (flutter_controller_) {
39 | flutter_controller_ = nullptr;
40 | }
41 |
42 | Win32Window::OnDestroy();
43 | }
44 |
45 | LRESULT
46 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
47 | WPARAM const wparam,
48 | LPARAM const lparam) noexcept {
49 | // Give Flutter, including plugins, an opportunity to handle window messages.
50 | if (flutter_controller_) {
51 | std::optional result =
52 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
53 | lparam);
54 | if (result) {
55 | return *result;
56 | }
57 | }
58 |
59 | switch (message) {
60 | case WM_FONTCHANGE:
61 | flutter_controller_->engine()->ReloadSystemFonts();
62 | break;
63 | }
64 |
65 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
66 | }
67 |
--------------------------------------------------------------------------------
/windows/runner/flutter_window.h:
--------------------------------------------------------------------------------
1 | #ifndef RUNNER_FLUTTER_WINDOW_H_
2 | #define RUNNER_FLUTTER_WINDOW_H_
3 |
4 | #include
5 | #include
6 |
7 | #include
8 |
9 | #include "win32_window.h"
10 |
11 | // A window that does nothing but host a Flutter view.
12 | class FlutterWindow : public Win32Window {
13 | public:
14 | // Creates a new FlutterWindow hosting a Flutter view running |project|.
15 | explicit FlutterWindow(const flutter::DartProject& project);
16 | virtual ~FlutterWindow();
17 |
18 | protected:
19 | // Win32Window:
20 | bool OnCreate() override;
21 | void OnDestroy() override;
22 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
23 | LPARAM const lparam) noexcept override;
24 |
25 | private:
26 | // The project to run.
27 | flutter::DartProject project_;
28 |
29 | // The Flutter instance hosted by this window.
30 | std::unique_ptr flutter_controller_;
31 | };
32 |
33 | #endif // RUNNER_FLUTTER_WINDOW_H_
34 |
--------------------------------------------------------------------------------
/windows/runner/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
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(200, 10);
29 | Win32Window::Size size(720/2, 1280/2);
30 | if (!window.Create(L"alist", 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/BFWXKJGS/AlistClient/98a794eb7c7ce70449ee20f0c1ccaa887812d9f8/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 | std::string utf8_string;
52 | if (target_length == 0 || target_length > utf8_string.max_size()) {
53 | return utf8_string;
54 | }
55 | utf8_string.resize(target_length);
56 | int converted_length = ::WideCharToMultiByte(
57 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
58 | -1, utf8_string.data(),
59 | target_length, nullptr, nullptr);
60 | if (converted_length == 0) {
61 | return std::string();
62 | }
63 | return utf8_string;
64 | }
65 |
--------------------------------------------------------------------------------
/windows/runner/utils.h:
--------------------------------------------------------------------------------
1 | #ifndef RUNNER_UTILS_H_
2 | #define RUNNER_UTILS_H_
3 |
4 | #include
5 | #include
6 |
7 | // Creates a console for the process, and redirects stdout and stderr to
8 | // it for both the runner and the Flutter library.
9 | void CreateAndAttachConsole();
10 |
11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
12 | // encoded in UTF-8. Returns an empty std::string on failure.
13 | std::string Utf8FromUtf16(const wchar_t* utf16_string);
14 |
15 | // Gets the command line arguments passed in as a std::vector,
16 | // encoded in UTF-8. Returns an empty std::vector on failure.
17 | std::vector GetCommandLineArguments();
18 |
19 | #endif // RUNNER_UTILS_H_
20 |
--------------------------------------------------------------------------------