Skip to content

Commit

Permalink
style/refactor: mode state management issue in the main screen
Browse files Browse the repository at this point in the history
fix: the entire widget tree was being rerendered and updated on mode state change
  • Loading branch information
rj-since-2000 committed Mar 24, 2021
1 parent bb41bc4 commit fddc3a7
Show file tree
Hide file tree
Showing 15 changed files with 522 additions and 360 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ ruTorrent ⇒ A web interface for rtorrent that uses that API. It also does othe

Thus, our Flutter application talks with ruTorrent's backend service to provide a native interface.

![Diagram](./assets/docs/ruTorrent%20Flutter%20Application%20Diagram.png)

## Usage

In order to use this flutter application you should have ruTorrent 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).
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 19 additions & 4 deletions lib/api/api_requests.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ class ApiRequests {

var items = jsonDecode(response.body)['items'];
for (var item in items) {
HistoryItem historyItem = HistoryItem(
item['name'], item['action'], item['action_time'], item['size']);
HistoryItem historyItem = HistoryItem(item['name'], item['action'],
item['action_time'], item['size'], item['hash']);
historyItems.add(historyItem);
}
general.updateHistoryItems(historyItems, context);
Expand Down Expand Up @@ -411,8 +411,8 @@ class ApiRequests {

List<HistoryItem> historyItems = [];
for (var item in items) {
HistoryItem historyItem = HistoryItem(
item['name'], item['action'], item['action_time'], item['size']);
HistoryItem historyItem = HistoryItem(item['name'], item['action'],
item['action_time'], item['size'], item['hash']);
historyItems.add(historyItem);
}
return historyItems;
Expand Down Expand Up @@ -470,4 +470,19 @@ class ApiRequests {
print(e.toString() + "errrrr");
}
}

static removeHistoryItem(Api api, String hashValue) async {
Fluttertoast.showToast(msg: 'Removing Torrent from History');
try {
await api.ioClient.post(Uri.parse(api.historyPluginUrl),
headers: api.getAuthHeader(),
body: {
'cmd': 'delete',
'mode': 'hstdelete',
'hash': hashValue,
});
} on Exception catch (e) {
print('err: ${e.toString()}');
}
}
}
210 changes: 114 additions & 96 deletions lib/components/add_url_bottom_sheet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,30 @@ class _AddBottomSheetState extends State<AddBottomSheet> {

final FocusNode urlFocus = FocusNode();

final _formKey = GlobalKey<FormState>();

String torrentPath;

File torrentFile;

// validating url through regex
bool isValidUrl(String input) {
var urlRegex = r'(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+';
if (RegExp(urlRegex).hasMatch(input)) {
return true;
} else {
return false;
}
}

// output a invalid error message if url is invalid
String urlValidator(String input) {
if (!isValidUrl(input)) {
return 'Please enter a valid url';
}
return null;
}

void pickTorrentFile() async {
FilePickerResult result = await FilePicker.platform
.pickFiles(type: FileType.custom, allowedExtensions: ["torrent"]);
Expand All @@ -47,112 +67,110 @@ class _AddBottomSheetState extends State<AddBottomSheet> {
@override
Widget build(BuildContext context) {
double wp = MediaQuery.of(context).size.width;
double bottomPadding = MediaQuery.of(context).viewInsets.bottom;
return Padding(
padding: EdgeInsets.only(bottom: bottomPadding),
child: Container(
height: 300,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
margin: EdgeInsets.symmetric(
horizontal: wp * 0.35,
),
height: 5,
color: Theme.of(context).primaryColor,
),
Text(
'Add link',
style: TextStyle(
fontSize: 14,
color: Provider.of<Mode>(context).isLightMode
? Colors.black54
: Colors.white),
),
Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 32),
child: DataInput(
borderColor: Provider.of<Mode>(context).isLightMode
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
margin: EdgeInsets.symmetric(
horizontal: wp * 0.35,
),
height: 5,
color: Theme.of(context).primaryColor,
),
Text(
'Add link',
style: TextStyle(
fontSize: 14,
color: Provider.of<Mode>(context).isLightMode
? Colors.black54
: Colors.white),
),
Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 32),
child: Form(
key: _formKey,
child: DataInput(
borderColor: Provider.of<Mode>(context).isLightMode
? Theme.of(context).primaryColor
: Colors.white,
textEditingController: urlTextController,
hintText: widget.dialogHint,
focus: urlFocus,
validator: urlValidator,
suffixIconButton: IconButton(
color: Provider.of<Mode>(context).isLightMode
? Theme.of(context).primaryColor
: Colors.white,
textEditingController: urlTextController,
hintText: widget.dialogHint,
focus: urlFocus,
suffixIconButton: IconButton(
color: Provider.of<Mode>(context).isLightMode
? Theme.of(context).primaryColor
: Colors.white,
onPressed: () async {
ClipboardData data = await Clipboard.getData('text/plain');
if (data != null)
urlTextController.text = data.text.toString();
if (urlFocus.hasFocus) urlFocus.unfocus();
},
icon: Icon(Icons.content_paste),
),
onPressed: () async {
ClipboardData data = await Clipboard.getData('text/plain');
if (data != null)
urlTextController.text = data.text.toString();
if (urlFocus.hasFocus) urlFocus.unfocus();
},
icon: Icon(Icons.content_paste),
),
),
Container(
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 36),
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
side: BorderSide(color: Theme.of(context).primaryColor),
),
side: BorderSide(color: Theme.of(context).primaryColor),
primary: Theme.of(context).primaryColor),
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 28, vertical: 16),
child: Text(
'Start Download',
style: TextStyle(color: Colors.white, fontSize: 18),
),
),
),
Container(
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 36),
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
side: BorderSide(color: Theme.of(context).primaryColor),
),
onPressed: () {
widget.apiRequest(urlTextController.text);
Navigator.pop(context);
},
side: BorderSide(color: Theme.of(context).primaryColor),
primary: Theme.of(context).primaryColor),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 16),
child: Text(
(widget.dialogHint == "Enter Rss Url")
? 'Add RSS Feed'
: 'Start Download',
style: TextStyle(color: Colors.white, fontSize: 18),
),
),
(widget.dialogHint == "Enter Rss Url")
? Container()
: Container(
padding: const EdgeInsets.symmetric(
vertical: 16, horizontal: 36),
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
side: BorderSide(
color: Theme.of(context).primaryColor),
),
side:
BorderSide(color: Theme.of(context).primaryColor),
primary: Theme.of(context).primaryColor),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 28, vertical: 16),
child: Text(
'Browse Torrent File',
style: TextStyle(color: Colors.white, fontSize: 18),
),
onPressed: () {
if (_formKey.currentState.validate()) {
widget.apiRequest(urlTextController.text);
Navigator.pop(context);
}
},
),
),
(widget.dialogHint == "Enter Rss Url")
? Container()
: Container(
padding:
const EdgeInsets.symmetric(vertical: 16, horizontal: 36),
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
side: BorderSide(color: Theme.of(context).primaryColor),
),
onPressed: () {
pickTorrentFile();
Navigator.pop(context);
},
side: BorderSide(color: Theme.of(context).primaryColor),
primary: Theme.of(context).primaryColor),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 28, vertical: 16),
child: Text(
'Browse Torrent File',
style: TextStyle(color: Colors.white, fontSize: 18),
),
),
],
),
),
onPressed: () {
pickTorrentFile();
Navigator.pop(context);
},
),
),
],
);
}
}
6 changes: 6 additions & 0 deletions lib/components/data_input.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class DataInput extends StatelessWidget {
final onFieldSubmittedCallback;
final textInputAction;
final Color borderColor;
final String Function(String) validator;

DataInput({
this.hintText,
Expand All @@ -22,6 +23,7 @@ class DataInput extends StatelessWidget {
this.textInputAction,
this.suffixIconButton,
this.borderColor,
this.validator,
});

@override
Expand All @@ -41,12 +43,16 @@ class DataInput extends StatelessWidget {
? Colors.black
: Colors.white,
keyboardType: TextInputType.text,
validator: validator,
decoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 16),
hintText: hintText,
hintStyle: TextStyle(color: hintTextColor ?? borderColor),
suffixIcon: suffixIconButton,
errorStyle: TextStyle(
fontSize: 16,
),
),
),
decoration: BoxDecoration(
Expand Down
Loading

0 comments on commit fddc3a7

Please sign in to comment.