ccextractor / rutorrent-flutter Goto Github PK
View Code? Open in Web Editor NEWA ruTorrent-based client in Flutter
License: MIT License
A ruTorrent-based client in Flutter
License: MIT License
Hello Everyone
Currently if Torrent name is long enough to occupy multiple lines, the text in second line gets clipped due to widget height constraints.
This is because TorrentTile
is a Container of fixed height of 80.
Solution is to define maxLines for the Torrent Name Text and provide it an overflow property.
If you find this to be valid, I would like to take up this issue.
A set of specific labels (video, audio, game, etc.) can be included in the labels column to easily identify a label like in the web.
@harchani-ritik I would like to work on this
The getTorrentList is returning null when there is no active torrent which is causing the shimmer effect to appear again and again
Log: flutter: Exception caught in Api Request NoSuchMethodError: Class 'List' has no instance getter 'keys'.
Receiver: Instance(length:0) of '_GrowableList'
Tried calling: keys
File Picker lets you pick files having extension other than .torrent and also does not notifies the user that a wrong file is picked.
There are some breaking changes in the flutter's network policy : https://flutter.dev/docs/release/breaking-changes/network-policy-ios-android
Because of these changes, the app even on putting a right URL in the location field gives a "Invalid" toast.
In general the local host runs on HTTP. So we need to allow the use of http connections in debug builds.
Class 'List<dynamic>' has no instance getter 'keys'.
I/flutter (31423): Receiver: Instance(length:0) of '_GrowableList'
I/flutter (31423): Tried calling: keys
There is no check for torrent list response from ApiRequest before accessing its path keys so when the torrent list is empty still it tries to access 'keys' getter which doesn't exist.
@harchani-ritik I propose to add a check for elements/size of response torrent list before accessing any of it's method to prevent this exception.
Currently the app UI has few unnecessary padding and widgets, and lacks minute detailing in the UI. Also some widgets need UX improvements like closing gestures and typical widget flow in the app. Improvements related to it will be resolved here without touching any major business logic or API.
List of improvements -
No
in SettingsPage -> _logoutAllAccounts dialog. Stability issue of the state of the widget's ancestor.It's great to review pull requests but at the same time it's a bit tough to make sure all the files are properly formatted, no warnings exist like unused variables & all tests are passing.
I suggest implementing GitHub workflow CI for the Rutorrent flutter app.
@harchani-ritik I am working on it and will soon open a PR for the same.
Currently to see the number of torrents in each state (All, Downloading, Completed, Active, etc...) is not shown in the drawer so the only way to count is to actively select a particular filter in the drawer and then to count torrents manually.
Each filter should also display the count for each state as in the web interface.
@harchani-ritik I propose to add count of states in the app drawer.
As of now, the app is expecting only good cases in which the APIs will respond with a positive message. I get to know about this issue when my rtorrent
server was closed but still, I am able to open the app and saw a lot of error logs inside CLI but nothing on the app.
I propose to improve the error handling inside the app which includes showing proper log messages when the app is unable to connect, showing error messages to the user about connectivity issues & some small issues too.
I'm currently updating Xcode to see if that could be the issue. I was on 11.3, and I'm about to try 12.4. I just wanted to file this in case someone else in the future comes across this.
% pod install
Traceback (most recent call last):
20: from /usr/local/bin/pod:23:in `<main>'
19: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems.rb:303:in `activate_bin_path'
18: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems.rb:303:in `synchronize'
17: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems.rb:304:in `block in activate_bin_path'
16: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/specification.rb:1420:in `activate'
15: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/specification.rb:1438:in `activate_dependencies'
14: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/specification.rb:1438:in `each'
13: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/specification.rb:1452:in `block in activate_dependencies'
12: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/specification.rb:1420:in `activate'
11: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/specification.rb:1438:in `activate_dependencies'
10: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/specification.rb:1438:in `each'
9: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/specification.rb:1452:in `block in activate_dependencies'
8: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/specification.rb:1420:in `activate'
7: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/specification.rb:1438:in `activate_dependencies'
6: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/specification.rb:1438:in `each'
5: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/specification.rb:1452:in `block in activate_dependencies'
4: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/specification.rb:1420:in `activate'
3: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/specification.rb:1438:in `activate_dependencies'
2: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/specification.rb:1438:in `each'
1: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/specification.rb:1449:in `block in activate_dependencies'
/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/dependency.rb:311:in `to_specs': Could not find 'ffi' (>= 1.3.0) among 79 total gem(s) (Gem::MissingSpecError)
Checked in 'GEM_PATH=/Users/rajohns/.gem/ruby/2.6.0:/Library/Ruby/Gems/2.6.0:/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0', execute `gem env` for more information
Upon clicking on torrent add/download notification user should be redirected to the torrent detail page.
I would like to work on this.
From the trace it looks like the new Threadpool implementation is the likely cause.
Steps to reproduce -
Flutter run
Log
E/MethodChannel#plugins.flutter.io/shared_preferences(31423): Failed to handle method call
E/MethodChannel#plugins.flutter.io/shared_preferences(31423): java.util.concurrent.RejectedExecutionException: Task io.flutter.plugins.sharedpreferences.MethodCallHandlerImpl$1@c5cdb16 rejected from java.util.concurrent.ThreadPoolExecutor@bf1c89f[Running, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 1]
E/MethodChannel#plugins.flutter.io/shared_preferences(31423): at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2086)
E/MethodChannel#plugins.flutter.io/shared_preferences(31423): at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:848)
E/MethodChannel#plugins.flutter.io/shared_preferences(31423): at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1394)
E/MethodChannel#plugins.flutter.io/shared_preferences(31423): at io.flutter.plugins.sharedpreferences.MethodCallHandlerImpl.commitAsync(MethodCallHandlerImpl.java:137)
E/MethodChannel#plugins.flutter.io/shared_preferences(31423): at io.flutter.plugins.sharedpreferences.MethodCallHandlerImpl.onMethodCall(MethodCallHandlerImpl.java:66)
E/MethodChannel#plugins.flutter.io/shared_preferences(31423): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233)
E/MethodChannel#plugins.flutter.io/shared_preferences(31423): at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:85)
E/MethodChannel#plugins.flutter.io/shared_preferences(31423): at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:818)
E/MethodChannel#plugins.flutter.io/shared_preferences(31423): at android.os.MessageQueue.nativePollOnce(Native Method)
E/MethodChannel#plugins.flutter.io/shared_preferences(31423): at android.os.MessageQueue.next(MessageQueue.java:336)
E/MethodChannel#plugins.flutter.io/shared_preferences(31423): at android.os.Looper.loop(Looper.java:174)
E/MethodChannel#plugins.flutter.io/shared_preferences(31423): at android.app.ActivityThread.main(ActivityThread.java:7710)
E/MethodChannel#plugins.flutter.io/shared_preferences(31423): at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#plugins.flutter.io/shared_preferences(31423): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
E/MethodChannel#plugins.flutter.io/shared_preferences(31423): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
E/flutter (31423): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: PlatformException(error, Task io.flutter.plugins.sharedpreferences.MethodCallHandlerImpl$1@2ecc23e rejected from java.util.concurrent.ThreadPoolExecutor@bf1c89f[Running, pool size = 1, active threads = 0, queued tasks = 0, completed tasks = 1], null, java.util.concurrent.RejectedExecutionException: Task io.flutter.plugins.sharedpreferences.MethodCallHandlerImpl$1@2ecc23e rejected from java.util.concurrent.ThreadPoolExecutor@bf1c89f[Running, pool size = 1, active threads = 0, queued tasks = 0, completed tasks = 1]
E/flutter (31423): at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2086)
E/flutter (31423): at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:848)
E/flutter (31423): at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1394)
E/flutter (31423): at io.flutter.plugins.sharedpreferences.MethodCallHandlerImpl.commitAsync(MethodCallHandlerImpl.java:137)
E/flutter (31423): at io.flutter.plugins.sharedpreferences.MethodCallHandlerImpl.onMethodCall(MethodCallHandlerImpl.java:66)
E/flutter (31423): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233)
E/flutter (31423): at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:85)
E/flutter (31423): at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:818)
E/flutter (31423): at android.os.MessageQueue.nativePollOnce(Native Method)
E/flutter (31423): at android.os.MessageQueue.next(MessageQueue.java:336)
E/flutter (31423): at android.os.Looper.loop(Looper.java:174)
E/flutter (31423): at android.app.ActivityThread.main(ActivityThread.java:7710)
E/flutter (31423): at java.lang.reflect.Method.invoke(Native Method)
E/flutter (31423): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
E/flutter (31423): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
E/flutter (31423): )
E/flutter (31423): #0 StandardMethodCodec.decodeEnvelope
package:flutter/…/services/message_codecs.dart:581
E/flutter (31423): #1 MethodChannel._invokeMethod
package:flutter/…/services/platform_channel.dart:158
E/flutter (31423): <asynchronous suspension>
E/flutter (31423): #2 MethodChannelSharedPreferencesStore.setValue
package:shared_preferences_platform_interface/method_channel_shared_preferences.dart:30
E/flutter (31423): <asynchronous suspension>
remove the red debug banner and also when a user what to login and there is an error it show invalid, i want to add a more meaningful error message instead of invalid,please can i proceed?
The spinner has currently aligned to the left and the videoViewController is not disposed which caused a performance issue.
@harchani-ritik I'd like to work on this
Log:
`[!] CocoaPods could not find compatible versions for pod "flutter_vlc_player":
In Podfile:
flutter_vlc_player (from '.symlinks/plugins/flutter_vlc_player/ios')
Specs satisfying the 'flutter_vlc_player (from '.symlinks/plugins/flutter_vlc_player/ios')' dependency were found, but they required a higher minimum deployment target.`
Specifications:
flutter: v1.20.0
Mac OS X 10.15.2
ios 8.0
Opening Explorer screen shows no files even though some files are downloaded and saved.
Log
I/flutter (29990): FormatException: Unexpected character (at character 1)
I/flutter (29990): <html>
I/flutter (29990): ^
Upon more debug I found the complete response which shows status code 404 from rutorrent backend.
I/flutter (29990): <html>
I/flutter (29990): <head><title>404 Not Found</title></head>
I/flutter (29990): <body>
I/flutter (29990): <center><h1>404 Not Found</h1></center>
I/flutter (29990): <hr><center>nginx</center>
I/flutter (29990): </body>
I/flutter (29990): </html>
The function causing this
/// Gets Disk Files
static Future<List<DiskFile>> getDiskFiles(Api api, String path) async {
try {
var response = await api.ioClient.post(Uri.parse(api.explorerPluginUrl),
headers: api.getAuthHeader(),
body: {
'cmd': 'get',
'src': path,
});
print(response.body);
var files = jsonDecode(response.body)['files'];
List<DiskFile> diskFiles = [];
for (var file in files) {
DiskFile diskFile = DiskFile();
diskFile.isDirectory = file['is_dir'];
diskFile.name = file['data']['name'];
diskFiles.add(diskFile);
}
return diskFiles;
} on Exception catch (e) {
print(e.toString());
return null;
}
}
@harchani-ritik Seems some problem with the file path !?
The video keeps playing in the background and the sound is turned on even when we are scrolling through the app explorer or when we turn off the phone display. This is happening due to the app not checking for lifecycle methods. The video should ideally be paused when the app lifecycle is inactive or paused and the video should play again when the lifecycle is resumed.
@harchani-ritik I'd like to work on this.
@harchani-ritik I would like to work on this
Hey!
I've been thinking about how some people might configure rutorrent using a RPI or similar devices on their home and access it through port forward or ssh tunneling services like remote.it and I was wondering maybe we should add a discovery helper. Also, since it seems like rTorrent & rutorrent is very much user-configured, we could add some instructions to set a permanent announcement through Avahi xml files.
We would need to agree on:
I could write a sample PR that adds this discovery through the setup interface, but comments are welcome.
The root widget of TorrentsListPage is Consumer<GeneralFeatures>
. Not mentioning all the functions inside GeneralFeatures, the two specific functions updateDiskSpace()
and setListOfLabels()
also notify change in the Consumer<GeneralFeatures>
as usual. One of these two functions is getting called over a stream getAllAccountsTorrentList()
in ApiRequests. Both the functions mentioned earlier are not utilised in the TorrentsListPage but because of these the Consumer<GeneralFeatures>
is providing change very frequently in the tree which is causing widget rebuild a lot more number of times than it should actually build. The actual use of these two functions is in the Drawer. All this occurred when the torrent list was not empty.
@harchani-ritik I would like to work on this. A simple solution I thought was to create a separate class of ChangeNotifier from GeneralFeatures so that functions used inside other widgets only consume providers needed. Also mention any suggestion from your side.
As of now, almost all the dart files are not formatted properly according to base dart rules. We can use the dart format
command to format all the files. Having a properly formatted code will help people to understand the project more easily and thus more contributing.
Let me know if this issue seems worth it to be addressed, I would like to land my first PR for this issue.
@harchani-ritik I'd like to add the android app icon to ios as well
As of now, the app logs out all accounts immediately by pressing the Logout button on the settings page. Ideally, It should ask for confirmation about the action since the user might accidentally tap the button.
I propose to add a confirmation dialog (AlertDialog) to prevent accidental clicks.
Path provider package giving error when switching to the downloads tab. This issue is due to incompatibility of getExternalStorageDirectory for iOS. Alternative is to save the file in the NSDocumentsDirectory (getApplicationDocumentsDirectory()) for platform=ios and then make it available to the user.
[VERBOSE-2:ui_dart_state.cc(186)] Unhandled Exception: Unsupported operation: Functionality only available on Android
#0 MethodChannelPathProvider.getExternalStoragePath (package:path_provider_platform_interface/src/method_channel_path_provider.dart:55:7)
#1 getExternalStorageDirectory (package:path_provider/path_provider.dart:125:39)
#2 _DownloadsPageState._initFiles (package:rutorrentflutter/pages/downloads_page.dart:25:29)
#3 _DownloadsPageState.initState (package:rutorrentflutter/pages/downloads_page.dart:21:5)
#4 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4632:57)
#5 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4469:5)
#6 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3541:14)
#7 Element.updateChild (package:flutter/src/widgets/framework.dart:3306:18)
#8 SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5974:14)
#9 Element.inflateWidget (package:f<…>
I'd like to fix this issue @harchani-ritik
The bottom padding of AppBottomSheet widget in lib/components/add_url_bottom_sheet.dart has a bottom padding which on keyboard focus causes a pixel overflow in some devices.
Are you working on this issue? - Yes
@harchani-ritik I would like to solve this issue
The consumer of Mode
is at the root of the Scaffold tree in the main_screen.dart which causes the entire tree to rebuild on switching from dark to light mode and vice versa, which is unnecessary and causes a bad user experience. Mode change should only affect the UI and not the business logic!
@harchani-ritik I propose to resolve this issue with provider<Mode>
instead of consumer<Mode>
so that only the UI is effected on switching the current mode and fix some other small state management issues too in the same screen.
In the torrents list page, we can sort by a list of options but there is no way we can remove this sorting. I think we can add a small clear selection
option to achieve it.
@harchani-ritik Let me know if I can work on this issue.
title field of BottomNavigationBar is deprecated. Use label instead.
Code will be more refactored for transitioning between pages.
There are several issue while migrating to flutter 2.0.0
error: The named parameter 'child' isn't defined. (undefined_named_parameter at [rutorrentflutter] lib/screens/torrent_details_screen.dart:139)
Flutter toast needs to be upgraded: In file included from /Users/pratikbaid/Developer/flutter/.pub-cache/hosted/pub.dartlang.org/fluttertoast-4.0.1/ios/Classes/FluttertoastPlugin.m:2: /Users/pratikbaid/Developer/flutter/.pub-cache/hosted/pub.dartlang.org/fluttertoast-4.0.1/ios/Classes/UIView+Toast.h:328:19: warning: empty paragraph passed to '@param' command [-Wdocumentation]
Modal bottom sheet version outdated
../../../../Developer/flutter/.pub-cache/hosted/pub.dartlang.org/modal_bottom_sheet-0.1.6+1/lib/src/material_with_modal_page_route.dart:21:16: Error: Getter not found: 'opaque'
Shared pref outdated
pub-cache/hosted/pub.dartlang.org/shared_preferences-0.5.8/android/src/main/java/io/flutter/plugins/sharedpreferences/SharedPreferencesPlugin.java:18: warning: [deprecation] Registrar in PluginRegistry has been deprecated
5 Raised Button
'RaisedButton' is deprecated and shouldn't be used. Use ElevatedButton instead. See the migration guide in flutter.dev/go/material-button-migration-guide). This feature was deprecated after v1.25.0-8.1.pre. • lib/components/add_url_bottom_sheet.dart:101:22 • deprecated_member_use
@harchani-ritik I'd like to fix this issue
Hello Everyone,
The App currently crashes in Explorer screen in debug mode and in release isLoading
flag always remains true and hence shimmer will always be shown.
This happens because there's no exception handling in getDiskFiles.
This can be solved by handling exceptions in getDiskFiles, return null in case of any exception and check if it returns null in disk_explorer_screen.
If you find the proposed solution to be valid, I will like to send a PR.
An Expanded widget must be a descendant of a Row, Column, or Flex, and the path from the Expanded widget to its enclosing Row, Column, or Flex must contain only StatelessWidgets or StatefulWidgets (not other kinds of widgets, like RenderObjectWidgets).
In this case if the history items list is empty, then a SVG image is build at the center of an expanded widget which is not a child of a Flex widget which causes an Exception caught by widgets library
in History screen.
@harchani-ritik I propose to resolve this issue using an appropriate Flex widget as an ancestor of Expanded widget.
ApiRequests shows adding torrent url and rss url with no url validation. Even an empty url shows no warning/error.
@harchani-ritik I propose to improve this by creating a validation logic for the urls and show a proper error message to the user in the UI if the url is empty.
The latest version of dart has a automated null safety check so migrating to null safety will allow us to not have to check for null values and this is also the default convention in the latest flutter version (V2)
@harchani-ritik I'd like to work on this.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.