├── .gitignore
├── LICENSE
├── README.md
├── analysis_options.yaml
├── android
├── .project
├── .settings
│ └── org.eclipse.buildship.core.prefs
├── app
│ ├── .classpath
│ ├── .project
│ ├── .settings
│ │ └── org.eclipse.buildship.core.prefs
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── deluge_client
│ │ │ │ └── MainActivity.kt
│ │ └── res
│ │ │ ├── drawable-v21
│ │ │ ├── ic_launcher.png
│ │ │ └── launch_background.xml
│ │ │ ├── drawable
│ │ │ ├── ic_launcher.png
│ │ │ └── launch_background.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-night
│ │ │ └── styles.xml
│ │ │ └── values
│ │ │ └── styles.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── assets
├── animation.gif
├── banner.png
├── fonts
│ └── SFUIDisplay
│ │ ├── sf-ui-display-heavy.otf
│ │ ├── sf-ui-display-light.otf
│ │ └── sf-ui-display-medium.otf
├── github.png
├── loader.gif
├── logo.png
├── no_data.png
├── poster.png
├── server_end_error.png
└── slack.png
├── ios
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Podfile
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
└── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-App-1024x1024@1x.png
│ │ ├── Icon-App-20x20@1x.png
│ │ ├── Icon-App-20x20@2x.png
│ │ ├── Icon-App-20x20@3x.png
│ │ ├── Icon-App-29x29@1x.png
│ │ ├── Icon-App-29x29@2x.png
│ │ ├── Icon-App-29x29@3x.png
│ │ ├── Icon-App-40x40@1x.png
│ │ ├── Icon-App-40x40@2x.png
│ │ ├── Icon-App-40x40@3x.png
│ │ ├── Icon-App-60x60@2x.png
│ │ ├── Icon-App-60x60@3x.png
│ │ ├── Icon-App-76x76@1x.png
│ │ ├── Icon-App-76x76@2x.png
│ │ └── Icon-App-83.5x83.5@2x.png
│ └── LaunchImage.imageset
│ │ ├── Contents.json
│ │ ├── LaunchImage.png
│ │ ├── LaunchImage@2x.png
│ │ ├── LaunchImage@3x.png
│ │ └── README.md
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ └── Runner-Bridging-Header.h
├── lib
├── api
│ ├── apis.dart
│ └── models
│ │ ├── settings.dart
│ │ └── torrent_prop.dart
├── components
│ ├── accounts.dart
│ ├── all_info.dart
│ ├── bottom_sheet
│ │ ├── add_magnet_uri.dart
│ │ ├── add_torrent.dart
│ │ ├── choose_account.dart
│ │ ├── qr_magnet_reader.dart
│ │ ├── sorter.dart
│ │ └── ssh_config.dart
│ ├── download_upload_pane.dart
│ ├── error_on_dash.dart
│ ├── licence.dart
│ ├── loader.dart
│ ├── no_data.dart
│ ├── progress_bar.dart
│ ├── sidebar.dart
│ ├── storage_indicator.dart
│ └── tile.dart
├── control_center
│ ├── theme.dart
│ ├── theme_changer.dart
│ └── theme_controller.dart
├── core
│ ├── all_acc.dart
│ └── auth_valid.dart
├── database
│ └── dbmanager.dart
├── main.dart
├── notification
│ └── notification_controller.dart
├── screens
│ ├── about.dart
│ ├── auth.dart
│ ├── auth_qr.dart
│ ├── dashboard.dart
│ ├── multi_dash.dart
│ └── splash.dart
├── settings
│ ├── client
│ │ └── client_setting.dart
│ └── deluge
│ │ ├── core_settings.dart
│ │ ├── deluge_setting.dart
│ │ └── type
│ │ ├── advance.dart
│ │ ├── basic.dart
│ │ ├── general.dart
│ │ ├── sftp_setting_field.dart
│ │ └── sftp_streaming_settings.dart
├── sftp_streaming
│ ├── image_streamer.dart
│ ├── sftp_explorer.dart
│ ├── video_dir.dart
│ └── web_spacer.dart
├── state_ware_house
│ └── state_ware_house.dart
└── string
│ ├── controller.dart
│ ├── magnet_detect.dart
│ └── sorter.dart
├── pubspec.lock
├── pubspec.yaml
├── test
└── widget_test.dart
├── user_guide.md
└── web
├── favicon.png
├── icons
├── Icon-192.png
└── Icon-512.png
├── index.html
└── manifest.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | .vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | .dart_tool/
26 | .flutter-plugins
27 | .flutter-plugins-dependencies
28 | .packages
29 | .pub-cache/
30 | .pub/
31 | /build/
32 |
33 | # Web related
34 | lib/generated_plugin_registrant.dart
35 |
36 | # Directory created by dartdoc
37 | # If you don't generate documentation locally you can remove this line.
38 | doc/api/
39 |
40 | # Avoid committing generated Javascript files:
41 | *.dart.js
42 | *.info.json # Produced by the --dump-info flag.
43 | *.js # When generated by dart2js. Don't specify *.js if your
44 | # project includes source files written in JavaScript.
45 | *.js_
46 | *.js.deps
47 | *.js.map
48 |
49 | # test coverage
50 | /coverage
51 |
52 | # Android related
53 | **/android/**/gradle-wrapper.jar
54 | **/android/.gradle
55 | **/android/captures/
56 | **/android/gradlew
57 | **/android/gradlew.bat
58 | **/android/key.properties
59 | **/android/local.properties
60 | **/android/**/GeneratedPluginRegistrant.java
61 | *.jks
62 | key*.properties
63 |
64 | # iOS/XCode related
65 | **/ios/**/*.mode1v3
66 | **/ios/**/*.mode2v3
67 | **/ios/**/*.moved-aside
68 | **/ios/**/*.pbxuser
69 | **/ios/**/*.perspectivev3
70 | **/ios/**/*sync/
71 | **/ios/**/.sconsign.dblite
72 | **/ios/**/.tags*
73 | **/ios/**/.vagrant/
74 | **/ios/**/DerivedData/
75 | **/ios/**/Icon?
76 | **/ios/**/Pods/
77 | **/ios/**/.symlinks/
78 | **/ios/**/profile
79 | **/ios/**/xcuserdata
80 | **/ios/.generated/
81 | **/ios/Flutter/.last_build_id
82 | **/ios/Flutter/App.framework
83 | **/ios/Flutter/Flutter.framework
84 | **/ios/Flutter/Flutter.podspec
85 | **/ios/Flutter/Generated.xcconfig
86 | **/ios/Flutter/app.flx
87 | **/ios/Flutter/app.zip
88 | **/ios/Flutter/flutter_assets/
89 | **/ios/Flutter/flutter_export_environment.sh
90 | **/ios/ServiceDefinitions.json
91 | **/ios/Runner/GeneratedPluginRegistrant.*
92 |
93 | # Exceptions to above rules.
94 | !**/ios/**/default.mode1v3
95 | !**/ios/**/default.mode2v3
96 | !**/ios/**/default.pbxuser
97 | !**/ios/**/default.perspectivev3
98 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
99 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 CCExtractor Development
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
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 | ## Demo Run
30 |
31 | https://user-images.githubusercontent.com/57806993/128637426-71d45add-9458-4175-a20f-89885f2cf1fd.mp4
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | ## About The Project
43 | Deluge is a lightweight, free, cross-platform BitTorrent Monitoring service.
44 | Deluge mobile client app interacts with deluge via WEB-JSONRPC and gives all the administrative abilites. The Web app, Desktop app and all other relevant documentation can be found at
45 | Deluge, and its repository can be found here.
46 |
47 | 
48 |
49 | ### Features in Client Application
50 | | Features | Support |
51 | |------------------------------------------------|------------------|
52 | | Single Account | ✅ (tested) |
53 | | Multiple Account | ✅ (tested) |
54 | | operation with single account | ✅ (tested) |
55 | | operate with multiple account at the same time | ✅ (tested) |
56 | | dark mode | ✅ (tested) |
57 | | Deluge settings with all options | ✅ (tested) |
58 | | Live notification | ✅ (tested) |
59 | | automatic troubleshoot on cookie expire | ✅ (tested) |
60 | | Filtering and searching sorting .. etc | ✅ (tested) |
61 | | resume pause delete .. all basic functionality | ✅ (tested) |
62 | | long press to select and select all | ✅ (tested) |
63 | | Manual login | ✅ (tested) |
64 | | Rapid login by Q.R Code on the go | ✅ (tested) |
65 | | can handle reverse proxied | ✅ (tested) |
66 | | Live storage tile | ✅ (tested) |
67 | | Add new torrent as file | ✅ (tested) |
68 | | Add new torrent by magnet link | ✅ (tested) |
69 | | Add new torrent by Q.R code on the go | ✅ (tested) |
70 | | file exploration | ✅ (tested) |
71 | | streaming torrent content | ✅ (tested) |
72 | | Ability to download torrent content to mobile device | ✅ (tested)|
73 |
74 | ## Usage
75 |
76 | In order to use this flutter application you should have Deluge configured on your system, after which you can connect your mobile on the same network as your system and use the app by entering the configuration (IP address).
77 |
78 | If you find any difficulty in running Deluge on your system, you can use this [docker image](https://hub.docker.com/r/linuxserver/deluge).
79 |
80 | ***Note: The primary usage of this application is to control Deluge hosted on your seedbox account.***
81 |
82 | ## Seedbox
83 |
84 | A seedbox is a dedicated BitTorrent server. Often they are rented out by companies called seedbox providers.
85 |
86 | Seedboxes usually have a high speed Internet connection. This allows users to download torrents quickly and seed the torrents for a long time.
87 |
88 | You can learn more about seedbox [here](https://en.wikipedia.org/wiki/Seedbox).
89 |
90 |
91 |
92 |
93 | ## Getting Started
94 |
95 | #### For setting up the development environment, follow the steps given below:
96 |
97 | 1. For making changes to the project, fork this repository using the green button on this page.
98 |
99 | 2. Clone your fork or this repository, as applicable-
100 |
101 | ```bash
102 | git clone https://github.com/CCExtractor/Deluge-mobile-remote-client.git
103 | cd Deluge-mobile-remote-client
104 | ```
105 |
106 | 3. Check for flutter setup and connected devices.
107 |
108 | ```bash
109 | flutter doctor
110 | ```
111 |
112 | 4. Run the app using
113 | ```bash
114 | flutter run
115 | ```
116 |
117 | For help getting started with Flutter, view our
118 | [online documentation](https://flutter.dev/docs), which offers tutorials,
119 | samples, guidance on mobile development, and a full API reference.
120 |
121 | ## Community
122 |
123 | * CCExtractor Development on [Slack](https://rhccgsoc15.slack.com/).
124 |
125 | ## License
126 |
127 | The project is released under the [MIT License](http://www.opensource.org/licenses/mit-license.php). The license can be found [here](LICENSE).
128 |
129 |
130 |
131 |
132 | ***Note: some of the images are taken from internet, I am not claiming that those images belongs to me. All the credits and copyrights belong to their respective owners.***
133 |
134 | ## Contact
135 | Mohammad Arshad
136 |
137 |
138 |
139 |
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/android/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | android
4 | Project android created by Buildship.
5 |
6 |
7 |
8 |
9 | org.eclipse.buildship.core.gradleprojectbuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.buildship.core.gradleprojectnature
16 |
17 |
18 |
19 | 1629546067328
20 |
21 | 30
22 |
23 | org.eclipse.core.resources.regexFilterMatcher
24 | node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/android/.settings/org.eclipse.buildship.core.prefs:
--------------------------------------------------------------------------------
1 | arguments=
2 | auto.sync=false
3 | build.scans.enabled=false
4 | connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
5 | connection.project.dir=
6 | eclipse.preferences.version=1
7 | gradle.user.home=
8 | java.home=C\:/Program Files/Java/jdk-15.0.1
9 | jvm.arguments=
10 | offline.mode=false
11 | override.workspace.settings=true
12 | show.console.view=true
13 | show.executions.view=true
14 |
--------------------------------------------------------------------------------
/android/app/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/android/app/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | app
4 | Project app created by Buildship.
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.buildship.core.gradleprojectbuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.jdt.core.javanature
21 | org.eclipse.buildship.core.gradleprojectnature
22 |
23 |
24 |
25 | 1629546067337
26 |
27 | 30
28 |
29 | org.eclipse.core.resources.regexFilterMatcher
30 | node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/android/app/.settings/org.eclipse.buildship.core.prefs:
--------------------------------------------------------------------------------
1 | connection.project.dir=..
2 | eclipse.preferences.version=1
3 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 |
4 | if (localPropertiesFile.exists()) {
5 | localPropertiesFile.withReader('UTF-8') { reader ->
6 | localProperties.load(reader)
7 | }
8 | }
9 |
10 | def flutterRoot = localProperties.getProperty('flutter.sdk')
11 | if (flutterRoot == null) {
12 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
13 | }
14 |
15 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
16 | if (flutterVersionCode == null) {
17 | flutterVersionCode = '1'
18 | }
19 |
20 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
21 | if (flutterVersionName == null) {
22 | flutterVersionName = '1.0'
23 | }
24 |
25 | apply plugin: 'com.android.application'
26 | apply plugin: 'kotlin-android'
27 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
28 | def keystoreProperties = new Properties()
29 | def keystorePropertiesFile = rootProject.file('key.properties')
30 | if (keystorePropertiesFile.exists()) {
31 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
32 | }
33 |
34 |
35 | android {
36 | compileSdkVersion 31
37 |
38 | sourceSets {
39 | main.java.srcDirs += 'src/main/kotlin'
40 | }
41 |
42 | defaultConfig {
43 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
44 | applicationId "com.cc_extractor.deluge_client"
45 | minSdkVersion 21
46 | targetSdkVersion 30
47 | versionCode flutterVersionCode.toInteger()
48 | versionName flutterVersionName
49 | }
50 | signingConfigs {
51 | release {
52 | keyAlias keystoreProperties['keyAlias']
53 | keyPassword keystoreProperties['keyPassword']
54 | storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
55 | storePassword keystoreProperties['storePassword']
56 | }
57 | }
58 | buildTypes {
59 | release {
60 | signingConfig signingConfigs.release
61 | minifyEnabled true
62 | useProguard true
63 |
64 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
65 | }
66 | }
67 |
68 | // buildTypes {
69 | // release {
70 | // // TODO: Add your own signing config for the release build.
71 | // // Signing with the debug keys for now, so `flutter run --release` works.
72 | // signingConfig signingConfigs.debug
73 | // minifyEnabled true
74 | // useProguard true
75 |
76 | // proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
77 |
78 |
79 | // }
80 | // }
81 | }
82 |
83 | flutter {
84 | source '../..'
85 | }
86 |
87 | dependencies {
88 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
89 | }
90 |
--------------------------------------------------------------------------------
/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | #Flutter Wrapper
2 | -keep class io.flutter.app.** { *; }
3 | -keep class io.flutter.plugin.** { *; }
4 | -keep class io.flutter.util.** { *; }
5 | -keep class io.flutter.view.** { *; }
6 | -keep class io.flutter.** { *; }
7 | -keep class io.flutter.plugins.** { *; }
8 | -keep class com.jcraft.** { *; }
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
12 |
19 |
23 |
27 |
32 |
36 |
37 |
38 |
39 |
40 |
41 |
43 |
46 |
49 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/example/deluge_client/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.cc_extractor.deluge_client
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/android/app/src/main/res/drawable-v21/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/android/app/src/main/res/drawable/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.6.10'
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:4.1.0'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | jcenter()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
7 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
4 | def properties = new Properties()
5 |
6 | assert localPropertiesFile.exists()
7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
8 |
9 | def flutterSdkPath = properties.getProperty("flutter.sdk")
10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
12 |
--------------------------------------------------------------------------------
/assets/animation.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/assets/animation.gif
--------------------------------------------------------------------------------
/assets/banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/assets/banner.png
--------------------------------------------------------------------------------
/assets/fonts/SFUIDisplay/sf-ui-display-heavy.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/assets/fonts/SFUIDisplay/sf-ui-display-heavy.otf
--------------------------------------------------------------------------------
/assets/fonts/SFUIDisplay/sf-ui-display-light.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/assets/fonts/SFUIDisplay/sf-ui-display-light.otf
--------------------------------------------------------------------------------
/assets/fonts/SFUIDisplay/sf-ui-display-medium.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/assets/fonts/SFUIDisplay/sf-ui-display-medium.otf
--------------------------------------------------------------------------------
/assets/github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/assets/github.png
--------------------------------------------------------------------------------
/assets/loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/assets/loader.gif
--------------------------------------------------------------------------------
/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/assets/logo.png
--------------------------------------------------------------------------------
/assets/no_data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/assets/no_data.png
--------------------------------------------------------------------------------
/assets/poster.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/assets/poster.png
--------------------------------------------------------------------------------
/assets/server_end_error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/assets/server_end_error.png
--------------------------------------------------------------------------------
/assets/slack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/assets/slack.png
--------------------------------------------------------------------------------
/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 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '9.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | use_frameworks!
32 | use_modular_headers!
33 |
34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
35 | end
36 |
37 | post_install do |installer|
38 | installer.pods_project.targets.each do |target|
39 | flutter_additional_ios_build_settings(target)
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/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/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/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/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/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/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/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/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/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/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/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/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/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/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/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/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/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/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/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/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/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/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/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/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/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/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CCExtractor/Deluge-mobile-remote-client/02fff48736f066b9d9c7d0ff1314f6ac1f64a8e4/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | deluge_client
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/lib/api/models/settings.dart:
--------------------------------------------------------------------------------
1 | class Settings {
2 | bool sendInfo;
3 | int infoSent;
4 | int daemonPort;
5 | bool allowRemote;
6 | bool preAllocateStorage;
7 | String downloadLocation;
8 | List listenPorts;
9 | String listenInterface;
10 | String outgoingInterface;
11 | String randomPort;
12 | int listenRandomPort;
13 | bool listenUseSysPort;
14 | bool listenReusePort;
15 | List outgoingPorts;
16 | String randomOutgoingPorts;
17 | bool copyTorrentFile;
18 | bool delCopyTorrentFile;
19 | String torrentfilesLocation;
20 | String pluginsLocation;
21 | bool prioritizeFirstLastPieces;
22 | bool sequentialDownload;
23 | bool dht;
24 | bool upnp;
25 | bool natpmp;
26 | bool utpex;
27 | bool lsd;
28 | int encInPolicy;
29 | int encOutPolicy;
30 | int encLevel;
31 | int maxConnectionsGlobal;
32 | int maxUploadSpeed;
33 | int maxDownloadSpeed;
34 | int maxUploadSlotsGlobal;
35 | int maxHalfOpenConnections;
36 | int maxConnectionsPerSecond;
37 | bool ignoreLimitsOnLocalNetwork;
38 | int maxConnectionsPerTorrent;
39 | int maxUploadSlotsPerTorrent;
40 | int maxUploadSpeedPerTorrent;
41 | int maxDownloadSpeedPerTorrent;
42 | List enabledPlugins;
43 | bool addPaused;
44 | int maxActiveSeeding;
45 | int maxActiveDownloading;
46 | int maxActiveLimit;
47 | bool dontCountSlowTorrents;
48 | bool queueNewToTop;
49 | bool stopSeedAtRatio;
50 | bool removeSeedAtRatio;
51 | int stopSeedRatio;
52 | int shareRatioLimit;
53 | int seedTimeRatioLimit;
54 | int seedTimeLimit;
55 | bool autoManaged;
56 | bool moveCompleted;
57 | String moveCompletedPath;
58 | List moveCompletedPathsList;
59 | List downloadLocationPathsList;
60 | bool pathChooserShowChooserButtonOnLocalhost;
61 | bool pathChooserAutoCompleteEnabled;
62 | String pathChooserAcceleratorString;
63 | int pathChooserMaxPopupRows;
64 | bool pathChooserShowHiddenFiles;
65 | bool newReleaseCheck;
66 | Map proxy;
67 | String peerTos;
68 | bool rateLimitIpOverhead;
69 | String geoipDbLocation;
70 | int cacheSize;
71 | int cacheExpiry;
72 | bool autoManagePreferSeeds;
73 | bool shared;
74 | bool superSeeding;
75 | String autoaddLocation;
76 |
77 | Settings(Map json) {
78 | this.sendInfo = json['send_info'];
79 | this.infoSent = json["info_sent"];
80 | this.daemonPort = json["daemon_port"];
81 | this.allowRemote = json["allow_remote"];
82 | this.preAllocateStorage = json["pre_allocate_storage"];
83 | this.downloadLocation = json["download_location"];
84 | this.listenPorts = json["listen_ports"];
85 | this.listenInterface = json["listen_interface"];
86 | this.outgoingInterface = json["outgoing_interface"];
87 | this.randomPort = json["random_port"];
88 | this.listenRandomPort = json["listen_random_port"];
89 | this.listenUseSysPort = json["listen_use_sys_port"];
90 | this.listenReusePort = json["listen_reuse_port"];
91 | this.outgoingPorts = json["outgoing_ports"];
92 | this.randomOutgoingPorts = json["random_outgoing_ports"];
93 | this.copyTorrentFile = json["copy_torrent_file"];
94 | this.delCopyTorrentFile = json["del_copy_torrent_file"];
95 | this.torrentfilesLocation = json["torrentfiles_location"];
96 | this.pluginsLocation = json["plugins_location"];
97 | this.prioritizeFirstLastPieces = json["prioritize_first_last_pieces"];
98 | this.sequentialDownload = json["sequential_download"];
99 | this.dht = json["dht"];
100 | this.upnp = json["upnp"];
101 | this.natpmp = json["natpmp"];
102 | this.utpex = json["utpex"];
103 | this.lsd = json["lsd"];
104 | this.encInPolicy = json["enc_in_policy"];
105 | this.encOutPolicy = json["enc_out_policy"];
106 | this.encLevel = json["enc_level"];
107 | this.maxConnectionsGlobal = json["max_connections_global"];
108 | this.maxUploadSpeed = json["max_upload_speed"];
109 | this.maxDownloadSpeed = json["max_download_speed"];
110 | this.maxUploadSlotsGlobal = json["max_upload_slots_global"];
111 | this.maxHalfOpenConnections = json["max_half_open_connections"];
112 | this.maxConnectionsPerSecond = json["max_connections_per_second"];
113 | this.ignoreLimitsOnLocalNetwork = json["ignore_limits_on_local_network"];
114 | this.maxConnectionsPerTorrent = json["max_connections_per_torrent"];
115 | this.maxUploadSlotsPerTorrent = json["max_upload_slots_per_torrent"];
116 | this.maxUploadSpeedPerTorrent = json["max_upload_speed_per_torrent"];
117 | this.maxDownloadSpeedPerTorrent = json["max_download_speed_per_torrent"];
118 | this.enabledPlugins = json["enabled_plugins"];
119 | this.addPaused = json["add_paused"];
120 | this.maxActiveSeeding = json["max_active_seeding"];
121 | this.maxActiveDownloading = json["max_active_downloading"];
122 | this.maxActiveLimit = json["max_active_limi"];
123 | this.dontCountSlowTorrents = json["dont_count_slow_torrents"];
124 | this.queueNewToTop = json["queue_new_to_top"];
125 | this.stopSeedAtRatio = json["stop_seed_at_ratio"];
126 | this.removeSeedAtRatio = json["remove_seed_at_ratio"];
127 | this.stopSeedRatio = json["stop_seed_ratio"];
128 | this.shareRatioLimit = json["share_ratio_limit"];
129 | this.seedTimeRatioLimit = json["seed_time_ratio_limit"];
130 | this.seedTimeLimit = json["seed_time_limit"];
131 | this.autoManaged = json["auto_managed"];
132 | this.moveCompleted = json["move_completed"];
133 | this.moveCompletedPath = json["move_completed_path"];
134 | this.moveCompletedPathsList = json["move_completed_paths_list"];
135 | this.downloadLocationPathsList = json["download_location_paths_list"];
136 | this.pathChooserShowChooserButtonOnLocalhost =
137 | json["path_chooser_show_chooser_button_on_localhost"];
138 | this.pathChooserAutoCompleteEnabled =
139 | json["path_chooser_auto_complete_enabled"];
140 | this.pathChooserAcceleratorString = json["path_chooser_accelerator_string"];
141 | this.pathChooserMaxPopupRows = json["path_chooser_max_popup_rows"];
142 | this.pathChooserShowHiddenFiles = json["path_chooser_show_hidden_files"];
143 | this.newReleaseCheck = json["new_release_check"];
144 | this.proxy = json["proxy"];
145 | this.peerTos = json["peer_tos"];
146 | this.rateLimitIpOverhead = json["rate_limit_ip_overhead"];
147 | this.geoipDbLocation = json["geoip_db_location"];
148 | this.cacheSize = json["cache_size"];
149 |
150 | this.cacheExpiry = json["cache_expiry"];
151 | this.autoManagePreferSeeds = json["auto_manage_prefer_seeds"];
152 | this.shared = json["shared"];
153 | this.superSeeding = json["super_seeding"];
154 | this.autoaddLocation = json["autoadd_location"];
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/lib/components/accounts.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:deluge_client/components/loader.dart';
3 | import 'package:deluge_client/database/dbmanager.dart';
4 | import 'package:deluge_client/screens/auth.dart';
5 | import 'package:flutter/material.dart';
6 | import 'package:deluge_client/control_center/theme.dart';
7 | import 'package:fluttertoast/fluttertoast.dart';
8 | import 'package:deluge_client/state_ware_house/state_ware_house.dart';
9 | import 'package:deluge_client/control_center/theme_controller.dart';
10 |
11 | class accounts extends StatefulWidget {
12 | final VoidCallback update_account_selection;
13 | final VoidCallback dashboard_state;
14 |
15 | accounts({Key key, this.update_account_selection, this.dashboard_state})
16 | : super(key: key);
17 | @override
18 | accountsState createState() => accountsState(
19 | key: key,
20 | update_account_selection: update_account_selection,
21 | dashboard_state: dashboard_state);
22 | }
23 |
24 | class accountsState extends State {
25 | final VoidCallback update_account_selection;
26 | final VoidCallback dashboard_state;
27 |
28 | accountsState({Key key, this.update_account_selection, this.dashboard_state});
29 |
30 | final DbbucketManager dbmanager = new DbbucketManager();
31 |
32 | int selected_account;
33 |
34 | void update_account_state(int id) async {
35 | states.update_account_state(id);
36 | }
37 |
38 | void fetch_selected_account() async {
39 | int mid = await states.state_selected_account();
40 | if (this.mounted) {
41 | setState(() {
42 | selected_account = mid;
43 | });
44 | }
45 | }
46 |
47 | void initState() {
48 | fetch_selected_account();
49 |
50 | super.initState();
51 | }
52 |
53 | List avail_acc = new List();
54 |
55 | prompt_to_delete(
56 | BuildContext context, int id, String account, int length_acc) {
57 | // set up the buttons
58 | Widget cancelButton = TextButton(
59 | child: Text(
60 | "Yes",
61 | style: TextStyle(
62 | color: Colors.white,
63 | fontSize: theme.alert_box_font_size,
64 | fontWeight: FontWeight.bold,
65 | fontFamily: theme.font_family),
66 | ),
67 | onPressed: () async {
68 | //some code
69 | if (length_acc > 1) {
70 | //if it is selected account and you wanted to delete it then
71 | avail_acc.remove(id);
72 | if (id == selected_account) {
73 | //-----------------
74 | if (this.mounted) {
75 | setState(() {
76 | selected_account = avail_acc[0];
77 |
78 | update_account_state(selected_account);
79 | });
80 | }
81 | update_account_selection();
82 | dashboard_state();
83 | //here i will add logic to reset sftp
84 | if (await states.get_sftP_reset_bool()) {
85 | states.reset_sftp_config();
86 | }
87 |
88 | //--------------------
89 |
90 | }
91 | //--------------
92 | dbmanager.deletebucket(id);
93 | Navigator.of(context, rootNavigator: true)
94 | .pop(); // for shutting the alertbox
95 | Navigator.of(context).pop(); //for closing sidebar
96 | toastMessage(account + " deleted successfully");
97 | } else if (length_acc == 1) {
98 | states.reset_auth(); // it will reset the auth state
99 | dbmanager.deletebucket(id);
100 | avail_acc.remove(id);
101 | states.make_it_first_time();
102 |
103 | Navigator.of(context, rootNavigator: true)
104 | .pop(); // for shutting the alertbox
105 | //------------it should also reset config
106 | dbmanager.delete_table(); // it will delete whole table
107 |
108 | //--------------------------
109 |
110 | Navigator.pushReplacement(
111 | context,
112 | MaterialPageRoute(
113 | builder: (context) => auth_view(
114 | tow_attachment: false,
115 | )));
116 | }
117 | },
118 | );
119 | Widget continueButton = TextButton(
120 | child: Text(
121 | "No",
122 | style: TextStyle(
123 | color: Colors.blue,
124 | fontSize: theme.alert_box_font_size,
125 | fontWeight: FontWeight.bold,
126 | fontFamily: theme.font_family),
127 | ),
128 | onPressed: () {
129 | Navigator.of(context, rootNavigator: true).pop();
130 | },
131 | );
132 |
133 | // set up the AlertDialog
134 | AlertDialog alert = AlertDialog(
135 | backgroundColor: theme.base_color,
136 | title: Text("Pay Attention",
137 | style: TextStyle(color: Colors.white, fontFamily: theme.font_family)),
138 | content: Text(
139 | "Do you wanted to remove " + account,
140 | style: TextStyle(
141 | fontSize: theme.alert_box_font_size,
142 | color: Colors.white,
143 | fontFamily: theme.font_family),
144 | ),
145 | actions: [
146 | cancelButton,
147 | continueButton,
148 | ],
149 | );
150 |
151 | // show the dialog
152 | showDialog(
153 | context: context,
154 | barrierDismissible: false,
155 | builder: (BuildContext context) {
156 | return alert;
157 | },
158 | );
159 | }
160 |
161 | void toastMessage(String message) {
162 | Fluttertoast.showToast(
163 | msg: message,
164 | toastLength: Toast.LENGTH_SHORT,
165 | gravity: ToastGravity.BOTTOM,
166 | fontSize: 16.0,
167 | backgroundColor: Colors.black,
168 | );
169 | }
170 |
171 | @override
172 | Widget build(BuildContext context) {
173 | return Container(
174 | height: 140.0,
175 | child: FutureBuilder(
176 | future: dbmanager.getbucketitem(),
177 | builder: (BuildContext context, AsyncSnapshot snapshot) {
178 | if (snapshot.data == null) {
179 | return Container(child: Center(child: loader()));
180 | } else {
181 | List accounts = snapshot.data;
182 |
183 | return ListView.builder(
184 | itemCount: accounts == null ? 0 : accounts.length,
185 | itemBuilder: (BuildContext context, int index) {
186 | avail_acc.add(accounts[index].id);
187 | return ListTile(
188 | visualDensity:
189 | VisualDensity(horizontal: 0, vertical: -4),
190 | title: Text(accounts[index].deluge_url,
191 | // overflow: TextOverflow.ellipsis,
192 | style: TextStyle(
193 | fontSize: 12.0,
194 | fontFamily: theme.font_family,
195 | color: theme_controller.is_it_dark()
196 | ? Colors.white
197 | : Colors.black,
198 | )),
199 | leading: Icon(selected_account == accounts[index].id
200 | ? Icons.radio_button_checked
201 | : Icons.radio_button_unchecked),
202 | trailing: IconButton(
203 | icon: Icon(
204 | Icons.delete,
205 | color: Colors.red,
206 | size: 18.0,
207 | ),
208 | onPressed: () {
209 | prompt_to_delete(context, accounts[index].id,
210 | accounts[index].deluge_url, accounts.length);
211 | },
212 | ),
213 | onTap: () async {
214 | if (this.mounted) {
215 | setState(() {
216 | selected_account = accounts[index].id;
217 |
218 | update_account_state(selected_account);
219 | });
220 | }
221 | update_account_selection();
222 | dashboard_state();
223 | //here i will add logic to reset sftp
224 | if (await states.get_sftP_reset_bool()) {
225 | states.reset_sftp_config();
226 | }
227 | Navigator.of(context).pop(); //closing side bar
228 | },
229 | );
230 | });
231 | }
232 | }));
233 | }
234 | }
235 |
--------------------------------------------------------------------------------
/lib/components/all_info.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:expandable/expandable.dart';
3 | import 'package:deluge_client/control_center/theme.dart';
4 | import 'package:intl/intl.dart';
5 |
6 | import 'package:deluge_client/api/models/torrent_prop.dart';
7 |
8 | class more_info extends StatelessWidget {
9 | final Properties inside_res;
10 | final bool paused;
11 | more_info({Key key, @required this.inside_res, this.paused})
12 | : super(key: key);
13 |
14 | final format = new DateFormat('dd-MM-yyyy hh:mm a');
15 | final eta = new DateFormat('hh:mm');
16 |
17 | @override
18 | Widget build(BuildContext context) {
19 | buildItem(String label) {
20 | return Padding(
21 | padding: const EdgeInsets.all(10.0),
22 | child: Text(label),
23 | );
24 | }
25 |
26 | buildList() {
27 | return Column(
28 | children: [
29 | ListTile(
30 | dense: true,
31 | visualDensity: VisualDensity(horizontal: 0, vertical: -4),
32 | title: Text(
33 | "ETA",
34 | style: TextStyle(fontSize: 12.0, fontFamily: theme.font_family),
35 | ),
36 | subtitle: Text(
37 | !paused
38 | ? (inside_res.eta ~/ 60).toString() +
39 | ":" +
40 | (inside_res.eta % 60).toString()
41 | : "_:_",
42 | style: TextStyle(fontSize: 14.0, fontFamily: theme.font_family),
43 | ),
44 | ),
45 | ListTile(
46 | dense: true,
47 | visualDensity: VisualDensity(horizontal: 0, vertical: -4),
48 | title: Text(
49 | "Save path",
50 | style: TextStyle(fontSize: 12.0, fontFamily: theme.font_family),
51 | ),
52 | subtitle: Text(
53 | inside_res.savePath,
54 | style: TextStyle(fontSize: 14.0, fontFamily: theme.font_family),
55 | ),
56 | ),
57 | ListTile(
58 | dense: true,
59 | visualDensity: VisualDensity(horizontal: 0, vertical: -4),
60 | title: Text(
61 | "Is shared?",
62 | style: TextStyle(fontSize: 12.0, fontFamily: theme.font_family),
63 | ),
64 | subtitle: Text(
65 | inside_res.shared.toString(),
66 | style: TextStyle(fontSize: 14.0, fontFamily: theme.font_family),
67 | ),
68 | ),
69 | ListTile(
70 | dense: true,
71 | visualDensity: VisualDensity(horizontal: 0, vertical: -4),
72 | title: Text(
73 | "Is Private?",
74 | style: TextStyle(fontSize: 12.0, fontFamily: theme.font_family),
75 | ),
76 | subtitle: Text(
77 | inside_res.private.toString(),
78 | style: TextStyle(fontSize: 14.0, fontFamily: theme.font_family),
79 | ),
80 | ),
81 | ListTile(
82 | dense: true,
83 | visualDensity: VisualDensity(horizontal: 0, vertical: -4),
84 | title: Text(
85 | "Total peers",
86 | style: TextStyle(fontSize: 12.0, fontFamily: theme.font_family),
87 | ),
88 | subtitle: Text(
89 | inside_res.numPeers.toString(),
90 | style: TextStyle(fontSize: 14.0, fontFamily: theme.font_family),
91 | ),
92 | ),
93 | ListTile(
94 | dense: true,
95 | visualDensity: VisualDensity(horizontal: 0, vertical: -4),
96 | title: Text(
97 | "Total seeds",
98 | style: TextStyle(fontSize: 12.0, fontFamily: theme.font_family),
99 | ),
100 | subtitle: Text(
101 | inside_res.numSeeds.toString(),
102 | style: TextStyle(fontSize: 14.0, fontFamily: theme.font_family),
103 | ),
104 | ),
105 | ListTile(
106 | dense: true,
107 | visualDensity: VisualDensity(horizontal: 0, vertical: -4),
108 | title: Text(
109 | "Date and time added",
110 | style: TextStyle(fontSize: 12.0, fontFamily: theme.font_family),
111 | ),
112 | subtitle: Text(
113 | format
114 | .format(DateTime.fromMillisecondsSinceEpoch(
115 | inside_res.timeAdded * 1000))
116 | .toString(),
117 | style: TextStyle(fontSize: 14.0, fontFamily: theme.font_family),
118 | ),
119 | ),
120 | ],
121 | );
122 | }
123 |
124 | return ExpandableNotifier(
125 | child: ScrollOnExpand(
126 | child: ExpandablePanel(
127 | theme: const ExpandableThemeData(
128 | tapBodyToExpand: true,
129 | tapBodyToCollapse: true,
130 | hasIcon: false,
131 | ),
132 | header: ExpandableIcon(
133 | theme: const ExpandableThemeData(
134 | expandIcon: Icons.arrow_drop_down,
135 | collapseIcon: Icons.arrow_drop_up,
136 | iconColor: Colors.black,
137 | iconSize: 20.0,
138 | iconPadding: EdgeInsets.only(right: 5),
139 | hasIcon: false,
140 | ),
141 | ),
142 | collapsed: Container(),
143 | expanded: buildList(),
144 | ),
145 | ),
146 | );
147 | }
148 | }
149 | //------------------------------------
150 |
--------------------------------------------------------------------------------
/lib/components/bottom_sheet/add_magnet_uri.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter/services.dart';
5 | import 'package:deluge_client/control_center/theme.dart';
6 | import 'package:deluge_client/api/apis.dart';
7 | import 'package:deluge_client/string/magnet_detect.dart';
8 | import 'package:fluttertoast/fluttertoast.dart';
9 |
10 | class add_magnet extends StatefulWidget {
11 | final List cookie;
12 | final VoidCallback refresh;
13 | //-----------------------------------
14 | final String url;
15 | final String is_reverse_proxied;
16 | final String seed_username;
17 | final String seed_pass;
18 | final String qr_auth;
19 | add_magnet(
20 | {Key key,
21 | @required this.refresh,
22 | @required this.cookie,
23 | @required this.url,
24 | @required this.is_reverse_proxied,
25 | @required this.seed_username,
26 | @required this.seed_pass,
27 | @required this.qr_auth})
28 | : super(key: key);
29 | @override
30 | _add_magnetState createState() => _add_magnetState(
31 | refresh: refresh,
32 | cookie: cookie,
33 | url: url,
34 | is_reverse_proxied: is_reverse_proxied,
35 | seed_username: seed_username,
36 | seed_pass: seed_pass,
37 | qr_auth: qr_auth);
38 | }
39 |
40 | class _add_magnetState extends State {
41 | final VoidCallback refresh;
42 | final List cookie;
43 | //--------------------------------------
44 | final String url;
45 | final String is_reverse_proxied;
46 | final String seed_username;
47 | final String seed_pass;
48 | final String qr_auth;
49 |
50 | _add_magnetState(
51 | {this.cookie,
52 | this.refresh,
53 | this.url,
54 | this.is_reverse_proxied,
55 | this.seed_username,
56 | this.seed_pass,
57 | this.qr_auth});
58 | var myController = TextEditingController();
59 | String input = "";
60 | Future fetch_clipboard() async {
61 | ClipboardData data = await Clipboard.getData(Clipboard.kTextPlain);
62 | input = data.text;
63 | if (this.mounted) {
64 | setState(() {
65 | myController.text = input;
66 | });
67 | }
68 | }
69 |
70 | void toastMessage(String message) {
71 | Fluttertoast.showToast(
72 | msg: message,
73 | toastLength: Toast.LENGTH_SHORT,
74 | gravity: ToastGravity.BOTTOM,
75 | fontSize: 16.0,
76 | backgroundColor: Colors.black,
77 | );
78 | }
79 |
80 | void add_torrent_by_magnet_uri(String link) async {
81 | if (magnet_detect.parse(link)) {
82 | apis.add_magnet(link, cookie, url, is_reverse_proxied, seed_username,
83 | seed_pass, qr_auth, context);
84 |
85 | // after adding file then it should refresh it self;
86 | Navigator.of(context).pop(); //bottom sheet should get closed
87 | Future.delayed(Duration(seconds: 1), () {
88 | refresh();
89 | });
90 | } else {
91 | toastMessage("Please enter correct link");
92 | }
93 | }
94 |
95 | @override
96 | Widget build(BuildContext context) {
97 | return SingleChildScrollView(
98 | child: Material(
99 | shape: RoundedRectangleBorder(
100 | borderRadius: new BorderRadius.only(
101 | topRight: Radius.circular(15.0), topLeft: Radius.circular(15.0)),
102 | ),
103 | child: Container(
104 | padding:
105 | EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
106 | child: Column(
107 | mainAxisSize: MainAxisSize.min,
108 | children: [
109 | Divider(
110 | color: Color.fromRGBO(255, 79, 90, 1),
111 | thickness: 4.0,
112 | indent: 70.0,
113 | endIndent: 70.0,
114 | ),
115 | Padding(
116 | padding: EdgeInsets.all(10.0),
117 | child: TextField(
118 | onChanged: (String val) {
119 | setState(() {
120 | myController.text;
121 | });
122 | },
123 | style: TextStyle(
124 | color: Colors.black,
125 | fontSize: theme.alert_box_font_size,
126 | fontFamily: theme.font_family),
127 | decoration: new InputDecoration(
128 | border: new OutlineInputBorder(
129 | borderRadius: const BorderRadius.all(
130 | const Radius.circular(10.0),
131 | ),
132 | ),
133 | filled: true,
134 | hintStyle: new TextStyle(color: Colors.grey[800]),
135 | hintText: "Enter Magnet URL",
136 | suffixIcon: InkWell(
137 | child: Icon(Icons.paste),
138 | onTap: () {
139 | fetch_clipboard();
140 | },
141 | ),
142 | fillColor: Colors.white70,
143 | ),
144 | controller: myController,
145 | autofocus: true,
146 | )),
147 | ElevatedButton(
148 | onPressed: () {
149 | if (myController.text.length > 0) {
150 | add_torrent_by_magnet_uri(myController.text);
151 | }
152 | },
153 | style: ButtonStyle(
154 | backgroundColor: MaterialStateProperty.all(
155 | myController.text.length > 0 ? theme.base_color : Colors.grey,
156 | )),
157 | child: Text(
158 | "Add",
159 | style: TextStyle(
160 | color: Colors.black,
161 | fontSize: theme.alert_box_font_size,
162 | fontFamily: theme.font_family),
163 | ),
164 | )
165 | ],
166 | )),
167 | ));
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/lib/components/bottom_sheet/add_torrent.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 | import 'dart:io';
3 |
4 | import 'package:flutter/material.dart';
5 | import 'package:fluttertoast/fluttertoast.dart';
6 | import 'package:deluge_client/components/bottom_sheet/add_magnet_uri.dart';
7 | import 'package:deluge_client/components/bottom_sheet/qr_magnet_reader.dart';
8 | import 'package:deluge_client/control_center/theme.dart';
9 | import 'package:deluge_client/api/apis.dart';
10 | import 'package:deluge_client/control_center/theme_controller.dart';
11 | import 'package:file_picker/file_picker.dart';
12 | import 'package:flutter/services.dart';
13 |
14 | class add_new extends StatefulWidget {
15 | final VoidCallback refresh;
16 | final List cookie;
17 | //---------------
18 | final String url;
19 | final String is_reverse_proxied;
20 | final String seed_username;
21 | final String seed_pass;
22 | final String qr_auth;
23 | add_new(
24 | {Key key,
25 | @required this.cookie,
26 | @required this.refresh,
27 | @required this.url,
28 | @required this.is_reverse_proxied,
29 | @required this.seed_username,
30 | @required this.seed_pass,
31 | @required this.qr_auth})
32 | : super(key: key);
33 |
34 | @override
35 | _add_newState createState() => _add_newState(
36 | cookie: cookie,
37 | refresh: refresh,
38 | url: url,
39 | is_reverse_proxied: is_reverse_proxied,
40 | seed_username: seed_username,
41 | seed_pass: seed_pass,
42 | qr_auth: qr_auth);
43 | }
44 |
45 | class _add_newState extends State {
46 | final VoidCallback refresh;
47 | final List cookie;
48 | //----------------------------
49 | final String url;
50 | final String is_reverse_proxied;
51 | final String seed_username;
52 | final String seed_pass;
53 | final String qr_auth;
54 |
55 | _add_newState(
56 | {this.cookie,
57 | this.refresh,
58 | this.url,
59 | this.is_reverse_proxied,
60 | this.seed_username,
61 | this.seed_pass,
62 | this.qr_auth});
63 | void toastMessage(String message) {
64 | Fluttertoast.showToast(
65 | msg: message,
66 | toastLength: Toast.LENGTH_SHORT,
67 | gravity: ToastGravity.BOTTOM,
68 | fontSize: 16.0,
69 | backgroundColor: Colors.black,
70 | );
71 | }
72 |
73 | void add_new_torrent_file() async {
74 | String _fileName;
75 | List _paths;
76 |
77 | try {
78 | _paths = (await FilePicker.platform.pickFiles(
79 | type: FileType.custom,
80 | allowMultiple: false,
81 | onFileLoading: (FilePickerStatus status) => print(status),
82 | allowedExtensions: ["torrent"]))
83 | .files;
84 | } on PlatformException catch (e) {
85 | print("Unsupported operation" + e.toString());
86 | } catch (ex) {
87 | print(ex);
88 | }
89 | String file_path = "";
90 |
91 | file_path = _paths != null ? _paths.map((e) => e.path).toString() : '...';
92 | if (!mounted) {
93 | toastMessage("Please retry to add");
94 | }
95 | print(file_path.substring(1, file_path.length - 1));
96 |
97 | List torrent_byte =
98 | new File(file_path.substring(1, file_path.length - 1))
99 | .readAsBytesSync();
100 |
101 | if (torrent_byte.isNotEmpty) {
102 | String base_64_encoded_file = base64Encode(torrent_byte);
103 | apis.add_torrent_file(base_64_encoded_file, cookie, url,
104 | is_reverse_proxied, seed_username, seed_pass, qr_auth, context);
105 | Future.delayed(Duration(seconds: 1), () {
106 | refresh();
107 | });
108 | }
109 | }
110 |
111 | @override
112 | Widget build(BuildContext context) {
113 | return Material(
114 | child: SafeArea(
115 | top: false,
116 | child: Container(
117 | child: Column(
118 | mainAxisSize: MainAxisSize.min,
119 | children: [
120 | Padding(
121 | padding: EdgeInsets.only(top: 3.0),
122 | child: Text("Add new torrent as",
123 | style: TextStyle(
124 | color: (!theme_controller.is_it_dark()
125 | ? Colors.black
126 | : Colors.white),
127 | fontSize: theme.bottom_sheet_heading_font_size,
128 | fontFamily: theme.font_family))),
129 | Divider(
130 | color: theme.base_color,
131 | thickness: 4.0,
132 | indent: 55.0,
133 | endIndent: 55.0,
134 | ),
135 | ListTile(
136 | title: Text(
137 | 'Add torrent file',
138 | style: TextStyle(
139 | color: (!theme_controller.is_it_dark()
140 | ? Colors.black
141 | : Colors.white),
142 | fontSize: theme.alert_box_font_size,
143 | fontFamily: theme.font_family),
144 | ),
145 | leading:
146 | Icon(Icons.folder_rounded, color: theme.base_color),
147 | onTap: () {
148 | Navigator.of(context).pop();
149 | add_new_torrent_file();
150 | },
151 | ),
152 | ListTile(
153 | title: Text(
154 | 'Add magnet link',
155 | style: TextStyle(
156 | color: (!theme_controller.is_it_dark()
157 | ? Colors.black
158 | : Colors.white),
159 | fontSize: theme.alert_box_font_size,
160 | fontFamily: theme.font_family),
161 | ),
162 | leading: Icon(Icons.link_sharp, color: theme.base_color),
163 | onTap: () {
164 | Navigator.of(context).pop();
165 | showModalBottomSheet(
166 | isScrollControlled: true,
167 | context: context,
168 | backgroundColor: Colors.transparent,
169 | builder: (context) => add_magnet(
170 | cookie: cookie,
171 | url: url,
172 | is_reverse_proxied: is_reverse_proxied,
173 | seed_username: seed_username,
174 | seed_pass: seed_pass,
175 | qr_auth: qr_auth,
176 | refresh: () => refresh(),
177 | ));
178 | }),
179 | ListTile(
180 | title: Text(
181 | 'Scan magnet QR',
182 | style: TextStyle(
183 | color: (!theme_controller.is_it_dark()
184 | ? Colors.black
185 | : Colors.white),
186 | fontSize: theme.alert_box_font_size,
187 | fontFamily: theme.font_family),
188 | ),
189 | leading: Icon(Icons.qr_code_scanner_outlined,
190 | color: theme.base_color),
191 | onTap: () {
192 | Navigator.of(context).pop();
193 | showModalBottomSheet(
194 | isScrollControlled: false,
195 | context: context,
196 | backgroundColor: Colors.transparent,
197 | builder: (context) => magnet_qr_reader(
198 | cookie: cookie,
199 | url: url,
200 | is_reverse_proxied: is_reverse_proxied,
201 | seed_username: seed_username,
202 | seed_pass: seed_pass,
203 | qr_auth: qr_auth,
204 | refresh: () => refresh(),
205 | ));
206 | }),
207 | ],
208 | ),
209 | )));
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/lib/components/bottom_sheet/choose_account.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:deluge_client/components/bottom_sheet/add_torrent.dart';
4 | import 'package:deluge_client/database/dbmanager.dart';
5 | import 'package:deluge_client/settings/deluge/deluge_setting.dart';
6 | import 'package:flutter/material.dart';
7 | import 'package:deluge_client/control_center/theme.dart';
8 | import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
9 |
10 | class multi_account_menu extends StatefulWidget {
11 | final int widget_id;
12 | final Map cookie_all_account;
13 | final VoidCallback refresh;
14 | multi_account_menu(
15 | {Key key, this.cookie_all_account, this.refresh, this.widget_id})
16 | : super(key: key);
17 | @override
18 | _multi_account_menuState createState() => _multi_account_menuState(
19 | cookie_all_account: cookie_all_account,
20 | refresh: refresh,
21 | widget_id: widget_id);
22 | }
23 |
24 | class _multi_account_menuState extends State {
25 | final int widget_id;
26 | final Map cookie_all_account;
27 | final VoidCallback refresh;
28 |
29 | _multi_account_menuState(
30 | {this.cookie_all_account, this.refresh, this.widget_id});
31 | final DbbucketManager dbmanager = new DbbucketManager();
32 | void switch_to_next(
33 | List cookie,
34 | String url,
35 | String is_reverse_proxied,
36 | String seed_username,
37 | String seed_pass,
38 | String qr_auth) {
39 | Navigator.of(context).pop();
40 | showCupertinoModalBottomSheet(
41 | expand: false,
42 | context: context,
43 | backgroundColor: Colors.transparent,
44 | builder: (context) => add_new(
45 | cookie: cookie,
46 | url: url,
47 | is_reverse_proxied: is_reverse_proxied,
48 | seed_username: seed_username,
49 | seed_pass: seed_pass,
50 | qr_auth: qr_auth,
51 | refresh: () => refresh()));
52 | }
53 |
54 | @override
55 | Widget build(BuildContext context) {
56 | return Material(
57 | child: SafeArea(
58 | top: false,
59 | child: Container(
60 | height: 400.0,
61 | child: Column(
62 | children: [
63 | Padding(
64 | padding: EdgeInsets.only(top: 3.0),
65 | child: Text("Please Choose Account",
66 | style: TextStyle(
67 | fontSize: theme.bottom_sheet_heading_font_size,
68 | fontFamily: theme.font_family))),
69 | Divider(
70 | color: theme.base_color,
71 | thickness: 4.0,
72 | indent: 55.0,
73 | endIndent: 55.0,
74 | ),
75 | Expanded(
76 | child: FutureBuilder(
77 | future: dbmanager.getbucketitem(),
78 | builder:
79 | (BuildContext context, AsyncSnapshot snapshot) {
80 | if (snapshot.data == null) {
81 | return Container(
82 | child: Center(
83 | child:
84 | Image.asset('assets/loader.gif')));
85 | } else {
86 | List accounts = snapshot.data;
87 |
88 | return ListView.builder(
89 | itemCount:
90 | accounts == null ? 0 : accounts.length,
91 | itemBuilder:
92 | (BuildContext context, int index) {
93 | return ListTile(
94 | visualDensity: VisualDensity(
95 | horizontal: 0, vertical: -4),
96 | leading: Icon(
97 | Icons.connect_without_contact_sharp,
98 | color: theme.base_color,
99 | ),
100 | title: Text(accounts[index].deluge_url,
101 | style: TextStyle(
102 | fontFamily: theme.font_family,
103 | fontSize: theme.minimal_font_size,
104 | )),
105 | onTap: () {
106 | if (widget_id == 1) {
107 | if (cookie_all_account != null) {
108 | switch_to_next(
109 | cookie_all_account[
110 | accounts[index]
111 | .deluge_url],
112 | accounts[index].deluge_url,
113 | accounts[index]
114 | .is_reverse_proxied,
115 | accounts[index].username,
116 | accounts[index].password,
117 | accounts[index].via_qr);
118 | }
119 | } else if (widget_id == -1) {
120 | Navigator.of(context)
121 | .pop(); //closing the bottom sheet
122 | Navigator.push(
123 | context,
124 | MaterialPageRoute(
125 | builder: (context) =>
126 | deluge_settings(
127 | cookie:
128 | cookie_all_account[
129 | accounts[
130 | index]
131 | .deluge_url],
132 | selected_account:
133 | accounts[
134 | index])));
135 | }
136 | },
137 | );
138 | });
139 | }
140 | })),
141 | ],
142 | ))));
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/lib/components/bottom_sheet/qr_magnet_reader.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:qr_code_scanner/qr_code_scanner.dart';
5 | import 'package:deluge_client/control_center/theme.dart';
6 | import 'package:deluge_client/api/apis.dart';
7 | import 'package:deluge_client/string/magnet_detect.dart';
8 | import 'package:fluttertoast/fluttertoast.dart';
9 |
10 | class magnet_qr_reader extends StatefulWidget {
11 | final VoidCallback refresh;
12 | final List cookie;
13 | //----------------------------------------
14 | final String url;
15 | final String is_reverse_proxied;
16 | final String seed_username;
17 | final String seed_pass;
18 | final String qr_auth;
19 | magnet_qr_reader(
20 | {Key key,
21 | @required this.cookie,
22 | @required this.refresh,
23 | @required this.url,
24 | @required this.is_reverse_proxied,
25 | @required this.seed_username,
26 | @required this.seed_pass,
27 | @required this.qr_auth})
28 | : super(key: key);
29 |
30 | @override
31 | _magnet_qr_readerState createState() => _magnet_qr_readerState(
32 | refresh: refresh,
33 | cookie: cookie,
34 | url: url,
35 | is_reverse_proxied: is_reverse_proxied,
36 | seed_username: seed_username,
37 | seed_pass: seed_pass,
38 | qr_auth: qr_auth);
39 | }
40 |
41 | class _magnet_qr_readerState extends State {
42 | final VoidCallback refresh;
43 | final List cookie;
44 | //-------------------------------------
45 | final String url;
46 | final String is_reverse_proxied;
47 | final String seed_username;
48 | final String seed_pass;
49 | final String qr_auth;
50 |
51 | _magnet_qr_readerState(
52 | {this.cookie,
53 | this.refresh,
54 | this.is_reverse_proxied,
55 | this.seed_username,
56 | this.seed_pass,
57 | this.url,
58 | this.qr_auth});
59 | Barcode result;
60 | QRViewController controller;
61 | final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
62 | // In order to get hot reload to work we need to pause the camera if the platform
63 | // is android, or resume the camera if the platform is iOS.
64 | // now no need to do this
65 | // @override
66 | // void reassemble() {
67 | // super.reassemble();
68 | // if (Platform.isAndroid) {
69 | // controller.pauseCamera();
70 | // }
71 | // controller.resumeCamera();
72 | // }
73 | @override
74 | void dispose() {
75 | controller?.dispose();
76 | super.dispose();
77 | }
78 |
79 | void toastMessage(String message) {
80 | Fluttertoast.showToast(
81 | msg: message,
82 | toastLength: Toast.LENGTH_SHORT,
83 | gravity: ToastGravity.BOTTOM,
84 | fontSize: 16.0,
85 | backgroundColor: Colors.black,
86 | );
87 | }
88 |
89 | void add_torrent_by_magnet_uri(String link) async {
90 | if (magnet_detect.parse(link)) {
91 | apis.add_magnet(link, cookie, url, is_reverse_proxied, seed_username,
92 | seed_pass, qr_auth, context);
93 |
94 | // after adding file then it should refresh it self;
95 |
96 | Future.delayed(Duration(seconds: 1), () {
97 | refresh();
98 | Navigator.of(context).pop();
99 | });
100 | } else {
101 | toastMessage("Magnet Q.R is invalid");
102 | }
103 | // // bottom sheet should get closed
104 | }
105 |
106 | @override
107 | Widget build(BuildContext context) {
108 | return Material(
109 | shape: RoundedRectangleBorder(
110 | borderRadius: new BorderRadius.only(
111 | topRight: Radius.circular(15.0), topLeft: Radius.circular(15.0)),
112 | ),
113 | child: SafeArea(
114 | top: false,
115 | child: Container(
116 | child: Column(mainAxisSize: MainAxisSize.min, children: [
117 | Row(
118 | mainAxisAlignment: MainAxisAlignment.center,
119 | children: [
120 | Flexible(
121 | fit: FlexFit.tight,
122 | child: Container(
123 | color: Colors.transparent,
124 | height: MediaQuery.of(context).orientation ==
125 | Orientation.portrait
126 | ? 300.0
127 | : 150.0,
128 | child: _build_qr(context),
129 | )),
130 | ],
131 | ),
132 | Flexible(
133 | child: ElevatedButton(
134 | style: ButtonStyle(
135 | backgroundColor:
136 | MaterialStateProperty.all(theme.base_color)),
137 | onPressed: () {
138 | if (result != null) {
139 | // print(result.code);
140 | add_torrent_by_magnet_uri(result.code);
141 | controller.stopCamera();
142 | Navigator.of(context).pop();
143 | } else {
144 | //todo i need to add a message here
145 | controller.stopCamera();
146 | Navigator.of(context).pop();
147 | }
148 | },
149 | child: Text(
150 | "read QR",
151 | style: TextStyle(
152 | color: Colors.white,
153 | fontSize: theme.alert_box_font_size,
154 | fontFamily: theme.font_family),
155 | ))),
156 | ]),
157 | )));
158 | }
159 |
160 | //-----------------
161 | Widget _build_qr(BuildContext context) {
162 | // For this example we check how width or tall the device is and change the scanArea and overlay accordingly.
163 | var scanArea = (MediaQuery.of(context).size.width < 400 ||
164 | MediaQuery.of(context).size.height < 400)
165 | ? 150.0
166 | : 300.0;
167 | // To ensure the Scanner view is properly sizes after rotation
168 | // we need to listen for Flutter SizeChanged notification and update controller
169 | return QRView(
170 | key: qrKey,
171 | onQRViewCreated: _onQRViewCreated,
172 | overlay: QrScannerOverlayShape(
173 | borderColor: theme.base_color,
174 | borderRadius: 10,
175 | borderLength: 30,
176 | borderWidth: 10,
177 | cutOutSize: scanArea),
178 | );
179 | }
180 |
181 | void _onQRViewCreated(QRViewController controller) {
182 | if (this.mounted) {
183 | setState(() {
184 | this.controller = controller;
185 | });
186 | }
187 | controller.scannedDataStream.listen((scanData) {
188 | if (this.mounted) {
189 | setState(() {
190 | result = scanData;
191 | });
192 | }
193 | });
194 | }
195 | }
196 |
--------------------------------------------------------------------------------
/lib/components/bottom_sheet/sorter.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:flutter/material.dart';
3 | import 'package:deluge_client/control_center/theme.dart';
4 | import 'package:deluge_client/string/sorter.dart';
5 | import 'package:deluge_client/control_center/theme_controller.dart';
6 |
7 | class sorter extends StatefulWidget {
8 | final VoidCallback rebuilt_list;
9 | sorter({Key key, this.rebuilt_list}) : super(key: key);
10 | @override
11 | _sorterState createState() => _sorterState(
12 | rebuilt_list: rebuilt_list,
13 | );
14 | }
15 |
16 | class _sorterState extends State {
17 | final VoidCallback rebuilt_list;
18 | _sorterState({Key key, this.rebuilt_list});
19 | @override
20 | Widget build(BuildContext context) {
21 | return Material(
22 | child: SafeArea(
23 | top: false,
24 | child: Container(
25 | child: Column(
26 | mainAxisSize: MainAxisSize.min,
27 | children: [
28 | Padding(
29 | padding: EdgeInsets.only(top: 3.0),
30 | child: Text("Sort as",
31 | style: TextStyle(
32 | color: !theme_controller.is_it_dark()
33 | ? Colors.black
34 | : Colors.white,
35 | fontSize: theme.bottom_sheet_heading_font_size,
36 | fontFamily: theme.font_family))),
37 | Divider(
38 | color: theme.base_color,
39 | thickness: 4.0,
40 | indent: 55.0,
41 | endIndent: 55.0,
42 | ),
43 | ListTile(
44 | title: Text(
45 | 'Sort by non-reverse order',
46 | style: TextStyle(
47 | color: sort_helper.non_reverse_order
48 | ? theme.base_color
49 | : (!theme_controller.is_it_dark()
50 | ? Colors.black
51 | : Colors.white),
52 | fontSize: theme.alert_box_font_size,
53 | fontFamily: theme.font_family),
54 | ),
55 | leading: Icon(Icons.arrow_upward,
56 | color: sort_helper.non_reverse_order
57 | ? theme.base_color
58 | : (!theme_controller.is_it_dark()
59 | ? Colors.black
60 | : Colors.white)),
61 | onTap: () {
62 | if (this.mounted) {
63 | setState(() {
64 | sort_helper.reverse_order = false;
65 | sort_helper.non_reverse_order = true;
66 | sort_helper.by_size_order = false;
67 | sort_helper.by_date_time = false;
68 | });
69 | }
70 | rebuilt_list();
71 | Navigator.of(context).pop();
72 | },
73 | ),
74 | ListTile(
75 | title: Text(
76 | 'Sort by reverse order',
77 | style: TextStyle(
78 | color: sort_helper.reverse_order
79 | ? theme.base_color
80 | : (!theme_controller.is_it_dark()
81 | ? Colors.black
82 | : Colors.white),
83 | fontSize: theme.alert_box_font_size,
84 | fontFamily: theme.font_family),
85 | ),
86 | leading: Icon(
87 | Icons.arrow_downward_rounded,
88 | color: sort_helper.reverse_order
89 | ? theme.base_color
90 | : (!theme_controller.is_it_dark()
91 | ? Colors.black
92 | : Colors.white),
93 | ),
94 | onTap: () {
95 | if (this.mounted) {
96 | setState(() {
97 | sort_helper.reverse_order = true;
98 | sort_helper.non_reverse_order = false;
99 | sort_helper.by_size_order = false;
100 | sort_helper.by_date_time = false;
101 | });
102 | }
103 | rebuilt_list();
104 |
105 | Navigator.of(context).pop();
106 | }),
107 | ListTile(
108 | title: Text(
109 | 'Sort by size',
110 | style: TextStyle(
111 | color: sort_helper.by_size_order
112 | ? theme.base_color
113 | : (!theme_controller.is_it_dark()
114 | ? Colors.black
115 | : Colors.white),
116 | fontSize: theme.alert_box_font_size,
117 | fontFamily: theme.font_family),
118 | ),
119 | leading: Icon(
120 | Icons.sd_storage_outlined,
121 | color: sort_helper.by_size_order
122 | ? theme.base_color
123 | : (!theme_controller.is_it_dark()
124 | ? Colors.black
125 | : Colors.white),
126 | ),
127 | onTap: () {
128 | if (this.mounted) {
129 | setState(() {
130 | sort_helper.reverse_order = false;
131 | sort_helper.non_reverse_order = false;
132 | sort_helper.by_size_order = true;
133 | sort_helper.by_date_time = false;
134 | });
135 | }
136 | rebuilt_list();
137 |
138 | Navigator.of(context).pop();
139 | }),
140 | ListTile(
141 | title: Text(
142 | 'Sort by date and time added',
143 | style: TextStyle(
144 | color: sort_helper.by_date_time
145 | ? theme.base_color
146 | : (!theme_controller.is_it_dark()
147 | ? Colors.black
148 | : Colors.white),
149 | fontSize: theme.alert_box_font_size,
150 | fontFamily: theme.font_family),
151 | ),
152 | leading: Icon(
153 | Icons.watch,
154 | color: sort_helper.by_date_time
155 | ? theme.base_color
156 | : (!theme_controller.is_it_dark()
157 | ? Colors.black
158 | : Colors.white),
159 | ),
160 | onTap: () {
161 | if (this.mounted) {
162 | setState(() {
163 | sort_helper.reverse_order = false;
164 | sort_helper.non_reverse_order = false;
165 | sort_helper.by_size_order = false;
166 | sort_helper.by_date_time = true;
167 | });
168 | }
169 | rebuilt_list();
170 |
171 | Navigator.of(context).pop();
172 | }),
173 | ],
174 | ),
175 | )));
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/lib/components/bottom_sheet/ssh_config.dart:
--------------------------------------------------------------------------------
1 | import 'package:deluge_client/database/dbmanager.dart';
2 | import 'package:deluge_client/sftp_streaming/sftp_explorer.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:deluge_client/control_center/theme.dart';
5 | import 'package:deluge_client/state_ware_house/state_ware_house.dart';
6 | import 'package:deluge_client/settings/deluge/core_settings.dart';
7 | import 'package:fluttertoast/fluttertoast.dart';
8 | import 'package:deluge_client/control_center/theme_controller.dart';
9 | import 'package:deluge_client/settings/deluge/type/sftp_setting_field.dart';
10 |
11 | class ssh_config extends StatefulWidget {
12 | final String direx;
13 |
14 | final Bucket selected_account;
15 | ssh_config({Key key, @required this.direx, @required this.selected_account})
16 | : super(key: key);
17 |
18 | @override
19 | _ssh_configState createState() =>
20 | _ssh_configState(direx: direx, selected_account: selected_account);
21 | }
22 |
23 | class _ssh_configState extends State {
24 | final String direx;
25 |
26 | final Bucket selected_account;
27 | _ssh_configState(
28 | {Key key, @required this.direx, @required this.selected_account});
29 |
30 | void update_sftp_settings() async {
31 | states.set_sftp_host(core_settings.sftp_host.text.toString());
32 | states.set_sftp_pass(core_settings.sftp_pass.text.toString());
33 | states.set_sftp_port(core_settings.sftpport.text.toString());
34 | states.set_sftp_route(core_settings.sftp_route_url.text.toString());
35 | states.set_sftp_username(core_settings.sftp_username.text.toString());
36 | }
37 |
38 | void toastMessage(String message) {
39 | Fluttertoast.showToast(
40 | msg: message,
41 | toastLength: Toast.LENGTH_SHORT,
42 | gravity: ToastGravity.BOTTOM,
43 | fontSize: 16.0,
44 | backgroundColor: Colors.black,
45 | );
46 | }
47 |
48 | @override
49 | Widget build(BuildContext context) {
50 | return SingleChildScrollView(
51 | child: Material(
52 | shape: RoundedRectangleBorder(
53 | borderRadius: new BorderRadius.only(
54 | topRight: Radius.circular(15.0),
55 | topLeft: Radius.circular(15.0)),
56 | ),
57 | child: Container(
58 | padding: EdgeInsets.only(
59 | bottom: MediaQuery.of(context).viewInsets.bottom),
60 | child: Column(
61 | children: [
62 | Padding(
63 | padding: EdgeInsets.only(top: 3.0),
64 | child: Text("Add SFTP Config",
65 | style: TextStyle(
66 | color: (!theme_controller.is_it_dark()
67 | ? Colors.black
68 | : Colors.white),
69 | fontSize: theme.bottom_sheet_heading_font_size,
70 | fontFamily: theme.font_family))),
71 | Divider(
72 | color: Color.fromRGBO(255, 79, 90, 1),
73 | thickness: 4.0,
74 | indent: 70.0,
75 | endIndent: 70.0,
76 | ),
77 | sftp_settings_fields(
78 | selected_account: selected_account,
79 | ),
80 | Row(
81 | children: [
82 | Padding(
83 | padding: EdgeInsets.only(left: 5.0),
84 | child: Icon(
85 | Icons.warning,
86 | )),
87 | Flexible(
88 | child: Padding(
89 | padding: EdgeInsets.only(left: 3.0),
90 | child: Text(
91 | "These Settings can be change later, from SFTP settings option",
92 | style: TextStyle(fontFamily: theme.font_family),
93 | )),
94 | )
95 | ],
96 | ),
97 | ElevatedButton(
98 | style: ButtonStyle(
99 | backgroundColor:
100 | MaterialStateProperty.all(theme.base_color)),
101 | onPressed: () {
102 | update_sftp_settings();
103 | toastMessage("Added Config");
104 | Navigator.of(context).pop(); //close bottom sheet
105 | Navigator.push(
106 | context,
107 | MaterialPageRoute(
108 | builder: (context) => files(
109 | direx: direx,
110 | host: core_settings.sftp_host.text
111 | .toString(),
112 | password: core_settings.sftp_pass.text
113 | .toString(),
114 | path: core_settings.sftp_route_url.text
115 | .toString(),
116 | port: core_settings.sftpport.text
117 | .toString(),
118 | username: core_settings
119 | .sftp_username.text
120 | .toString(),
121 | choosen_account: selected_account,
122 | )));
123 | },
124 | child: Text("Save Configuration",
125 | style: TextStyle(
126 | fontFamily: theme.font_family,
127 | fontSize: theme.minimal_font_size)))
128 | ],
129 | ))));
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/lib/components/download_upload_pane.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'dart:io';
4 | import 'package:filesize/filesize.dart';
5 | import "package:flutter/material.dart";
6 | import 'package:deluge_client/control_center/theme.dart';
7 | import 'package:deluge_client/api/apis.dart';
8 | import 'package:deluge_client/control_center/theme_controller.dart';
9 | import 'package:deluge_client/api/models/torrent_prop.dart';
10 |
11 | class network_speed extends StatefulWidget {
12 | final String torrent_id;
13 | final List cookie;
14 | final String tor_name;
15 | final String url;
16 | final String is_reverse_proxied;
17 | final String seed_username;
18 | final String seed_pass;
19 | final String qr_auth;
20 | final bool paused;
21 | final bool completed;
22 | const network_speed(
23 | {Key key,
24 | @required this.torrent_id,
25 | this.cookie,
26 | this.tor_name,
27 | this.url,
28 | this.is_reverse_proxied,
29 | this.seed_pass,
30 | this.seed_username,
31 | this.qr_auth,
32 | this.paused,
33 | this.completed})
34 | : super(key: key);
35 |
36 | @override
37 | network_speedState createState() => network_speedState(
38 | tor_id: torrent_id,
39 | tor_name: tor_name,
40 | cookie: cookie,
41 | url: url,
42 | is_reverse_proxied: is_reverse_proxied,
43 | seed_username: seed_username,
44 | seed_pass: seed_pass,
45 | qr_auth: qr_auth,
46 | paused: paused,
47 | completed: completed);
48 | }
49 |
50 | class network_speedState extends State {
51 | String tor_id;
52 | String tor_name;
53 | List cookie;
54 | final String url;
55 | final String is_reverse_proxied;
56 | final String seed_username;
57 | final String seed_pass;
58 | final String qr_auth;
59 | bool paused;
60 | bool completed;
61 | network_speedState(
62 | {this.tor_id,
63 | this.cookie,
64 | this.tor_name,
65 | this.url,
66 | this.is_reverse_proxied,
67 | this.seed_username,
68 | this.seed_pass,
69 | this.qr_auth,
70 | this.paused,
71 | this.completed});
72 | int download_speed_in_byte = 0;
73 | int upload_speed_in_byte = 0;
74 | String download_speed = "0.0 KB";
75 | String upload_speed = "0.0 KB";
76 | bool stop_listening_speeds = false;
77 | bool have_to_stop = false;
78 |
79 | Future fetch_speed() async {
80 | try {
81 | Map api_output = await apis.get_torrent_list(cookie,
82 | url, is_reverse_proxied, seed_username, seed_pass, qr_auth, context);
83 | if (api_output != null) {
84 | Properties properties = api_output[tor_id];
85 | if (this.mounted) {
86 | setState(() {
87 | completed = properties.isFinished;
88 | });
89 | }
90 |
91 | download_speed_in_byte = properties.downloadPayloadRate;
92 |
93 | upload_speed_in_byte = properties.uploadPayloadRate;
94 | print("Download size: " + filesize(download_speed_in_byte));
95 | if (this.mounted) {
96 | setState(() {
97 | download_speed = filesize(download_speed_in_byte);
98 | upload_speed = filesize(upload_speed_in_byte);
99 | });
100 | }
101 |
102 | if (completed || have_to_stop) {
103 | stop_listening_speeds = true;
104 | }
105 | }
106 | }
107 | // print(progress_percent);
108 | catch (e) {
109 | print(e);
110 | }
111 | }
112 |
113 | @override
114 | void initState() {
115 | // TODO: implement initState
116 | if (this.mounted) {
117 | setState(() {
118 | paused;
119 | });
120 | }
121 | trace_down_up_speed();
122 |
123 | super.initState();
124 | }
125 |
126 | void trace_down_up_speed() {
127 | if (!completed) {
128 | if (!paused) {
129 | Timer.periodic(Duration(seconds: 1), (timer) {
130 | if (stop_listening_speeds) {
131 | timer.cancel();
132 | }
133 | if (this.mounted) {
134 | setState(() {
135 | fetch_speed();
136 | });
137 | }
138 | });
139 | }
140 | }
141 | }
142 |
143 | void stop_listening_network_speed() {
144 | have_to_stop = true;
145 | }
146 |
147 | void start_listening_network_speed() {
148 | have_to_stop = false;
149 | stop_listening_speeds = false;
150 | }
151 |
152 | void make_pause() {
153 | paused = true;
154 | }
155 |
156 | void make_resume() {
157 | paused = false;
158 | }
159 |
160 | @override
161 | Widget build(BuildContext context) {
162 | return Row(
163 | children: [
164 | Icon(Icons.arrow_downward_sharp),
165 | Text(
166 | download_speed + "/S",
167 | style: TextStyle(
168 | color: (!theme_controller.is_it_dark()
169 | ? Colors.black
170 | : Colors.white),
171 | fontSize: 11.0,
172 | fontFamily: theme.font_family),
173 | ),
174 | Icon(Icons.arrow_upward),
175 | Text(upload_speed + "/S",
176 | style: TextStyle(
177 | color: (!theme_controller.is_it_dark()
178 | ? Colors.black
179 | : Colors.white),
180 | fontSize: 11.0,
181 | fontFamily: theme.font_family)),
182 | ],
183 | );
184 | }
185 | }
186 |
--------------------------------------------------------------------------------
/lib/components/error_on_dash.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:deluge_client/control_center/theme.dart';
3 |
4 | class error extends StatefulWidget {
5 | final VoidCallback retry;
6 | final String account_name;
7 | error({Key key, @required this.retry, this.account_name}) : super(key: key);
8 | @override
9 | _errorState createState() =>
10 | _errorState(retry: retry, account_name: account_name);
11 | }
12 |
13 | class _errorState extends State {
14 | final VoidCallback retry;
15 | final String account_name;
16 | _errorState({Key key, @required this.retry, this.account_name});
17 |
18 | @override
19 | Widget build(BuildContext context) {
20 | return Expanded(
21 | child: SingleChildScrollView(
22 | child: Column(
23 | children: [
24 | Row(
25 | children: [
26 | Flexible(
27 | fit: FlexFit.tight,
28 | child: Image.asset(
29 | "assets/server_end_error.png",
30 | height: 300.0,
31 | width: 300.0,
32 | ),
33 | )
34 | ],
35 | ),
36 | Padding(
37 | padding: EdgeInsets.all(13.0),
38 | child: Container(
39 | child: Column(
40 | children: [
41 | Text(
42 | "Deluge is not responding.",
43 | style: TextStyle(
44 | fontFamily: theme.font_family,
45 | fontWeight: FontWeight.bold),
46 | ),
47 | account_name != null
48 | ? Text(
49 | account_name,
50 | style: TextStyle(
51 | fontFamily: theme.font_family,
52 | ),
53 | )
54 | : new Container(
55 | height: 0.0,
56 | width: 0.0,
57 | ),
58 | Divider(
59 | color: theme.base_color,
60 | thickness: 4.0,
61 | indent: 55.0,
62 | endIndent: 55.0,
63 | ),
64 | ],
65 | ))),
66 | Row(
67 | children: [
68 | Icon(Icons.insights_outlined),
69 | Flexible(
70 | fit: FlexFit.tight,
71 | child: Padding(
72 | padding: EdgeInsets.only(left: 20.0),
73 | child: Text(
74 | "If you have just installed deluge at your remote location, you may need to log in on the web ui once.",
75 | style: TextStyle(fontFamily: theme.font_family))))
76 | ],
77 | ),
78 | Row(
79 | children: [
80 | Icon(Icons.insights_outlined),
81 | Flexible(
82 | fit: FlexFit.tight,
83 | child: Padding(
84 | padding: EdgeInsets.only(left: 20.0),
85 | child: Text("Deluge may be down.",
86 | style: TextStyle(fontFamily: theme.font_family))))
87 | ],
88 | ),
89 | Row(
90 | children: [
91 | Icon(Icons.insights_outlined),
92 | Flexible(
93 | fit: FlexFit.tight,
94 | child: Padding(
95 | padding: EdgeInsets.only(left: 20.0),
96 | child: Text(
97 | "Deluge is taking time to respond, May be some internal problem.",
98 | style: TextStyle(fontFamily: theme.font_family))))
99 | ],
100 | ),
101 | Row(
102 | children: [
103 | Icon(Icons.insights_outlined),
104 | Flexible(
105 | fit: FlexFit.tight,
106 | child: Padding(
107 | padding: EdgeInsets.only(left: 20.0),
108 | child: Text(
109 | "It may also possible that Deluge is working but it is taking time to respond.",
110 | style: TextStyle(fontFamily: theme.font_family))))
111 | ],
112 | ),
113 | ElevatedButton(
114 | style: ButtonStyle(
115 | elevation: MaterialStateProperty.all(5.0),
116 | backgroundColor: MaterialStateProperty.all(Colors.red)),
117 | onPressed: () {
118 | retry();
119 | },
120 | child: Text("Retry",
121 | style: TextStyle(
122 | fontFamily: theme.font_family, color: Colors.white)),
123 | )
124 | ],
125 | )));
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/lib/components/licence.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class license extends StatefulWidget {
4 | @override
5 | _licenseState createState() => _licenseState();
6 | }
7 |
8 | class _licenseState extends State {
9 | @override
10 | Widget build(BuildContext context) {
11 | return Text("""MIT License
12 |
13 | Copyright (c) 2021 CCExtractor Development
14 |
15 | Permission is hereby granted, free of charge, to any person obtaining a copy
16 | of this software and associated documentation files (the "Software"), to deal
17 | in the Software without restriction, including without limitation the rights
18 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19 | copies of the Software, and to permit persons to whom the Software is
20 | furnished to do so, subject to the following conditions:
21 |
22 | The above copyright notice and this permission notice shall be included in all
23 | copies or substantial portions of the Software.
24 |
25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 | SOFTWARE.
32 |
33 |
34 | """);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/lib/components/loader.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:deluge_client/control_center/theme.dart';
3 |
4 | class loader extends StatefulWidget {
5 | @override
6 | _loaderState createState() => _loaderState();
7 | }
8 |
9 | class _loaderState extends State {
10 | @override
11 | Widget build(BuildContext context) {
12 | return SizedBox(
13 | height: 200,
14 | width: 100,
15 | child: Center(
16 | child: CircularProgressIndicator(
17 | valueColor: new AlwaysStoppedAnimation(theme.base_color),
18 | )));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lib/components/no_data.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class no_data extends StatefulWidget {
4 | @override
5 | _no_dataState createState() => _no_dataState();
6 | }
7 |
8 | class _no_dataState extends State {
9 | @override
10 | Widget build(BuildContext context) {
11 | return Center(
12 | child: Image.asset(
13 | 'assets/no_data.png',
14 | ),
15 | );
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/lib/components/progress_bar.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:io';
3 | import 'package:deluge_client/control_center/theme.dart';
4 | import "package:flutter/material.dart";
5 | import 'package:percent_indicator/linear_percent_indicator.dart';
6 | import 'package:deluge_client/api/apis.dart';
7 | import 'package:deluge_client/notification/notification_controller.dart';
8 | import 'package:deluge_client/state_ware_house/state_ware_house.dart';
9 | import 'package:deluge_client/api/models/torrent_prop.dart';
10 |
11 | class download_progress extends StatefulWidget {
12 | final String torrent_id;
13 | final List cookie;
14 | final String tor_name;
15 | final double initial_progress;
16 | //--
17 | final String url;
18 | final String is_reverse_proxied;
19 | final String seed_username;
20 | final String seed_pass;
21 | final String qr_auth;
22 | final bool paused;
23 | final bool completed;
24 | final Function(bool) update_completion_state;
25 | final Function(bool) update_seeding_state;
26 | //-------------asking refresh function so we can refresh if it get download
27 | final VoidCallback refresh_list;
28 | const download_progress(
29 | {Key key,
30 | @required this.torrent_id,
31 | @required this.cookie,
32 | @required this.tor_name,
33 | @required this.url,
34 | @required this.is_reverse_proxied,
35 | @required this.seed_username,
36 | @required this.seed_pass,
37 | @required this.qr_auth,
38 | @required this.paused,
39 | @required this.initial_progress,
40 | @required this.update_completion_state,
41 | @required this.completed,
42 | @required this.refresh_list,
43 | @required this.update_seeding_state})
44 | : super(key: key);
45 |
46 | @override
47 | download_progressState createState() => download_progressState(
48 | tor_id: torrent_id,
49 | tor_name: tor_name,
50 | cookie: cookie,
51 | url: url,
52 | is_reverse_proxied: is_reverse_proxied,
53 | seed_username: seed_username,
54 | seed_pass: seed_pass,
55 | qr_auth: qr_auth,
56 | paused: paused,
57 | initial_progress: initial_progress,
58 | update_completion_state: update_completion_state,
59 | completed: completed,
60 | refresh: refresh_list,
61 | update_seeding_state: update_seeding_state);
62 | }
63 |
64 | class download_progressState extends State {
65 | String tor_id;
66 | String tor_name;
67 | List cookie;
68 | final double initial_progress;
69 | final Function(bool) update_completion_state;
70 | final Function(bool) update_seeding_state;
71 | //--
72 | bool completed;
73 |
74 | final String url;
75 | final String is_reverse_proxied;
76 | final String seed_username;
77 | final String seed_pass;
78 | final String qr_auth;
79 | bool paused;
80 | final VoidCallback refresh;
81 | bool seeding = false;
82 | download_progressState(
83 | {this.tor_id,
84 | this.cookie,
85 | this.tor_name,
86 | this.url,
87 | this.is_reverse_proxied,
88 | this.seed_username,
89 | this.seed_pass,
90 | this.qr_auth,
91 | this.paused,
92 | this.initial_progress,
93 | this.update_completion_state,
94 | this.completed,
95 | this.refresh,
96 | this.update_seeding_state});
97 | double progress_percent = 0;
98 | //-----------------
99 | bool stop_listening_progress = false;
100 | bool needs_to_stop_listening = false;
101 | void get_status() async {
102 | try {
103 | Map api_output = await apis.get_torrent_list(cookie,
104 | url, is_reverse_proxied, seed_username, seed_pass, qr_auth, context);
105 |
106 | if (api_output != null) {
107 | Properties content = await api_output[tor_id];
108 | double middletemp = content.progress;
109 |
110 | double temp = (middletemp / 100.0);
111 | print(temp);
112 | seeding = content.isSeed;
113 |
114 | if (this.mounted) {
115 | setState(() {
116 | progress_percent = temp;
117 | completed = content.isFinished;
118 | });
119 | }
120 |
121 | update_completion_state(completed);
122 | update_seeding_state(seeding);
123 |
124 | //--------------------------notification
125 | if (notification_status == true) {
126 | notification.store_ids.add(tor_id);
127 | int idt = notification.fetch_noti_id(tor_id);
128 | notification.notification_on_progress(
129 | tor_id,
130 | idt > 0 ? idt : 0,
131 | "torrents",
132 | tor_name,
133 | (progress_percent * 100).roundToDouble().toString() + " %",
134 | progress_percent.toInt() * 100);
135 | }
136 |
137 | if (temp == 1.0 || needs_to_stop_listening) {
138 | stop_listening_progress = true;
139 | }
140 | }
141 | } catch (e) {
142 | print(e);
143 | }
144 | }
145 |
146 | int progress_fire = 0;
147 | bool notification_status;
148 | @override
149 | void initState() {
150 | // TODO: implement initState
151 | if (this.mounted) {
152 | setState(() {
153 | paused;
154 | });
155 | }
156 | handle_first_progress();
157 | trace_download_progress_bar();
158 |
159 | //----------------------
160 | fetch_notification_settings();
161 |
162 | super.initState();
163 | }
164 |
165 | void fetch_notification_settings() async {
166 | bool mid = await states.fetch_notification_settings();
167 | setState(() {
168 | notification_status = mid;
169 | });
170 | }
171 |
172 | void handle_first_progress() {
173 | double temp = initial_progress / 100.0;
174 |
175 | if (this.mounted) {
176 | setState(() {
177 | progress_percent = temp;
178 | });
179 | }
180 | }
181 |
182 | void trace_download_progress_bar() {
183 | if (!completed) {
184 | if (!paused) {
185 | Timer.periodic(Duration(seconds: 1), (timer) {
186 | if (stop_listening_progress) {
187 | timer.cancel();
188 | }
189 |
190 | if (this.mounted) {
191 | setState(() {
192 | get_status();
193 | });
194 | }
195 | });
196 | }
197 | }
198 | }
199 |
200 | void stop_listening_progress_bar() {
201 | needs_to_stop_listening = true;
202 | }
203 |
204 | void start_listening_progress_bar() {
205 | needs_to_stop_listening = false;
206 | stop_listening_progress = false;
207 | }
208 |
209 | void make_pause() {
210 | paused = true;
211 | }
212 |
213 | void make_resume() {
214 | paused = false;
215 | }
216 |
217 | //Text(tor_id == null ? "" : tor_id);
218 | @override
219 | Widget build(BuildContext context) {
220 | return Expanded(
221 | child: Container(
222 | padding: EdgeInsets.all(15.0),
223 | child: new LinearPercentIndicator(
224 | width: MediaQuery.of(context).size.width - 120.0,
225 | animation: false,
226 | lineHeight: 15.0,
227 | animationDuration: 2000,
228 | percent: progress_percent,
229 | center: Text(
230 | (progress_percent * 100).toString().length >= 5
231 | ? (progress_percent * 100).toString().substring(0, 5) + " %"
232 | : (progress_percent * 100).roundToDouble().toString() + " %",
233 | style: TextStyle(
234 | color: Colors.white,
235 | fontFamily: theme.font_family,
236 | fontSize: 11.0),
237 | ),
238 | linearStrokeCap: LinearStrokeCap.roundAll,
239 | progressColor: (progress_percent * 100).roundToDouble() == 100.0
240 | ? theme.base_color
241 | : Colors.green,
242 | ),
243 | ));
244 | }
245 | }
246 |
247 | //----------------------------------------------------
248 |
--------------------------------------------------------------------------------
/lib/components/storage_indicator.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:io';
3 | import 'package:deluge_client/database/dbmanager.dart';
4 | import 'package:filesize/filesize.dart';
5 | import "package:flutter/material.dart";
6 | import 'package:deluge_client/control_center/theme.dart';
7 | import 'package:deluge_client/api/apis.dart';
8 | import 'package:deluge_client/state_ware_house/state_ware_house.dart';
9 |
10 | import '../string/controller.dart';
11 | import 'package:deluge_client/control_center/theme_controller.dart';
12 |
13 | class storage_indicator extends StatefulWidget {
14 | List cookie;
15 | final BuildContext context;
16 | storage_indicator({Key key, @required this.cookie, @required this.context})
17 | : super(key: key);
18 | @override
19 | _storage_indicatorState createState() =>
20 | _storage_indicatorState(cookie: cookie, context: context);
21 | }
22 |
23 | class _storage_indicatorState extends State {
24 | List cookie;
25 | final BuildContext context;
26 | _storage_indicatorState(
27 | {Key key, @required this.cookie, @required this.context});
28 |
29 | DbbucketManager account_manager = DbbucketManager();
30 | int selected_account = 0;
31 | Bucket selx_acc;
32 |
33 | void fetch_selectx_account() async {
34 | int mid = await states.state_selected_account();
35 |
36 | selected_account = mid;
37 | if (selected_account > 0) {
38 | selx_acc = await account_manager.get_acc_by_id(selected_account);
39 | }
40 | }
41 |
42 | void get_config() async {
43 | Future.delayed(Duration(seconds: 1), () async {
44 | Map conf = await apis.fetch_config(
45 | cookie != null
46 | ? cookie
47 | : await cookie_substitue(
48 | selx_acc.deluge_url,
49 | selx_acc.deluge_pwrd,
50 | selx_acc.has_deluge_pwrd,
51 | selx_acc.is_reverse_proxied,
52 | selx_acc.username,
53 | selx_acc.password,
54 | selx_acc.via_qr),
55 | selx_acc.deluge_url,
56 | selx_acc.is_reverse_proxied,
57 | selx_acc.username,
58 | selx_acc.password,
59 | selx_acc.via_qr,
60 | context);
61 | if (this.mounted) {
62 | setState(() {
63 | controller.path_controller = conf['result']['download_location'];
64 | });
65 | }
66 | });
67 | }
68 |
69 | void get_path_size() async {
70 | Future.delayed(Duration(seconds: 1), () async {
71 | int free_space = await apis.fetch_free_space(
72 | cookie != null
73 | ? cookie
74 | : await cookie_substitue(
75 | selx_acc.deluge_url,
76 | selx_acc.deluge_pwrd,
77 | selx_acc.has_deluge_pwrd,
78 | selx_acc.is_reverse_proxied,
79 | selx_acc.username,
80 | selx_acc.password,
81 | selx_acc.via_qr),
82 | controller.path_controller,
83 | selx_acc.deluge_url,
84 | selx_acc.is_reverse_proxied,
85 | selx_acc.username,
86 | selx_acc.password,
87 | selx_acc.via_qr,
88 | context);
89 | if (this.mounted) {
90 | setState(() {
91 | controller.storage_controller = filesize(free_space).toString();
92 | });
93 | }
94 | });
95 | }
96 |
97 | void initState() {
98 | fetch_selectx_account();
99 |
100 | get_config();
101 | get_path_size();
102 | super.initState();
103 | }
104 |
105 | Future> cookie_substitue(
106 | String url,
107 | String password,
108 | String has_deluge_pass,
109 | String is_reverse_proxied,
110 | String seed_username,
111 | String seed_pass,
112 | String qr_auth) async {
113 | cookie = await apis.authentication_to_deluge(url, password, has_deluge_pass,
114 | is_reverse_proxied, seed_username, seed_pass, qr_auth, context);
115 |
116 | print("it is executed");
117 | print(cookie);
118 |
119 | return cookie;
120 | }
121 |
122 | @override
123 | Widget build(BuildContext context) {
124 | return Row(
125 | children: [
126 | Flexible(
127 | fit: FlexFit.tight,
128 | child: Container(
129 | child: ListTile(
130 | dense: true,
131 | visualDensity: VisualDensity(horizontal: 0, vertical: -4),
132 | title: Text(controller.path_controller,
133 | style: TextStyle(
134 | fontSize: 12.0,
135 | fontFamily: theme.font_family,
136 | color: theme_controller.is_it_dark()
137 | ? Colors.white
138 | : Colors.black)),
139 | subtitle: Text(
140 | controller.storage_controller + " " + "Available ",
141 | style: theme.sidebar_tile_style,
142 | ),
143 | leading: Icon(Icons.sd_storage_sharp),
144 | )))
145 | ],
146 | );
147 | }
148 | }
149 |
150 | //----------------------------------------------------
151 |
--------------------------------------------------------------------------------
/lib/control_center/theme.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class theme {
4 | static String thread_title = "Deluge Mobile client";
5 | static Color material_color = Colors.red;
6 | static Color base_color = Color.fromRGBO(241, 94, 90, 1.0);
7 | static String font_family = "SFUIDisplay";
8 | static double heading_font_size = 20.0;
9 | static double minimal_font_size = 15.0;
10 | static double alert_box_font_size = 18.0;
11 | static double bottom_sheet_heading_font_size = 21.0;
12 | static TextStyle logo_text_style = TextStyle(
13 | fontFamily: font_family,
14 | fontSize: heading_font_size,
15 | fontWeight: FontWeight.bold,
16 | color: Colors.black);
17 | static TextStyle sidebar_tile_style =
18 | TextStyle(fontFamily: font_family, fontSize: 15.0, color: base_color);
19 |
20 | static double children_expension_tile_font_size = 12.0;
21 | static TextStyle app_bar_style = TextStyle(
22 | fontSize: 20.0, fontFamily: theme.font_family, color: Colors.white);
23 | static TextStyle warning_style = TextStyle(
24 | fontFamily: theme.font_family, fontSize: 15.0, color: Colors.white);
25 | }
26 |
--------------------------------------------------------------------------------
/lib/control_center/theme_changer.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:deluge_client/control_center/theme_controller.dart';
3 |
4 | class ThemeBuilder extends StatefulWidget {
5 | final Widget Function(BuildContext context, Brightness brightness) builder;
6 |
7 | ThemeBuilder({this.builder});
8 |
9 | @override
10 | _ThemeBuilderState createState() => _ThemeBuilderState();
11 |
12 | static _ThemeBuilderState of(BuildContext context) {
13 | return context.findAncestorStateOfType();
14 | }
15 | }
16 |
17 | class _ThemeBuilderState extends State {
18 | Brightness extracted_current_theme;
19 | @override
20 | void initState() {
21 | super.initState();
22 | fetch_current_theme();
23 | }
24 |
25 | void fetch_current_theme() async {
26 | extracted_current_theme = await theme_controller.get_set_theme();
27 | if (mounted) {
28 | setState(() {
29 | theme_controller.brightness = extracted_current_theme;
30 | });
31 | }
32 | }
33 |
34 | void changeTheme() {
35 | setState(() {
36 | theme_controller.brightness =
37 | theme_controller.brightness == Brightness.dark
38 | ? Brightness.light
39 | : Brightness.dark;
40 | });
41 | }
42 |
43 | void set_theme(Brightness br) {
44 | theme_controller.brightness = br;
45 | }
46 |
47 | Brightness getCurrentTheme() {
48 | return theme_controller.brightness;
49 | }
50 |
51 | @override
52 | Widget build(BuildContext context) {
53 | return widget.builder(context, theme_controller.brightness);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/lib/control_center/theme_controller.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:deluge_client/state_ware_house/state_ware_house.dart';
3 |
4 | class theme_controller {
5 | static Brightness brightness;
6 | static bool is_it_dark() {
7 | return theme_controller.brightness == Brightness.dark;
8 | }
9 |
10 | static List brt_set = [
11 | Brightness.light,
12 | Brightness.dark,
13 | ];
14 | //--------------------------------------------------------------------------
15 | static Future get_set_theme() async {
16 | int index = await states.get_theme_mode();
17 |
18 | switch (index) {
19 | case 1:
20 | return brt_set[0];
21 | case 2:
22 | return brt_set[1];
23 | default:
24 | return brt_set[0];
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/lib/core/all_acc.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:deluge_client/database/dbmanager.dart';
4 | import 'package:deluge_client/api/apis.dart';
5 | import 'package:flutter/widgets.dart';
6 | import 'package:deluge_client/api/models/torrent_prop.dart';
7 |
8 | class all_account_core {
9 | static final DbbucketManager db = new DbbucketManager();
10 |
11 | static Map all_account_cookie = Map();
12 | static Future