-
Notifications
You must be signed in to change notification settings - Fork 7.8k
Desktop photo search #174
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Desktop photo search #174
Conversation
|
FYI @csells |
…top_photo_search
redbrogdon
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some drive-by comments. I'll try to get back to this ASAP.
| @override | ||
| Widget build(BuildContext context) { | ||
| final photoSearchModel = Provider.of<PhotoSearchModel>(context); | ||
| menubar.setApplicationMenu([ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this something that could/should be moved out of the build method? The fact that the widget's being built doesn't necessarily imply it's actively on the screen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The menu action has an implicit linkage to this window through the callback's construction of a dialog in the window. The only way I can see to make this work is for this code to be run during build, so that it has access to the build context for showDialog. Happy to take guidance if my understanding of this constraint is incorrect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, the need for a context weirds things up. I was mostly operating on my "build methods should avoid side effects wherever possible" instincts.
This reminds me of a situation I went to Hans for advice on: I wanted a network refresh for some data to be kicked off whenever the app navigated to a widget (DetailsScreen, I think it was). I had the update call initiating in a build method, but IIRC Hans suggested having my own Route object to do it.
At the moment, I don't have any real advice to offer, so stick with what you've got. I'm curious now, though, and I may ask Hans about it next week. 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fun part is that the menu will change depending on which window is selected for input in the user's window stack, which is independent of the repaint cycle.
| final PhotoDetailsPhotoSaveCallback onPhotoSave; | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) => SingleChildScrollView( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Generally, arrow syntax should be used for simple one-liners. While it works here, it increase rightward drift of the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Converted back to block syntax
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can break this out into builder methods and/or subsidiary widgets. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Broken out some of the content into a builder method, and added some animation to make the initial transition from no loaded image to loaded image less janky.
| @override | ||
| Widget build(BuildContext context) { | ||
| final photoSearchModel = Provider.of<PhotoSearchModel>(context); | ||
| menubar.setApplicationMenu([ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, the need for a context weirds things up. I was mostly operating on my "build methods should avoid side effects wherever possible" instincts.
This reminds me of a situation I went to Hans for advice on: I wanted a network refresh for some data to be kicked off whenever the app navigated to a widget (DetailsScreen, I think it was). I had the update call initiating in a build method, but IIRC Hans suggested having my own Route object to do it.
At the moment, I don't have any real advice to offer, so stick with what you've got. I'm curious now, though, and I may ask Hans about it next week. 😄
|
|
||
| if (body is Map && body['errors'] is List && body['errors'].isNotEmpty) { | ||
| final apiError = ApiError.fromJson(response.body); | ||
| throw UnsplashException(apiError.errors.join(', ')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider trapping other issues (json failing to parse on line 64, for instance) and returning this exception class as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added handling for invalid JSON response
| @@ -0,0 +1,350 @@ | |||
| // Copyright 2019 The Flutter team. All rights reserved. | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this something you wrote in concert with Hans, or is it something he did for a different project that also works here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code was lifted and adapted from a gist put together by @HansMuller.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @csells, the original idea for this sample was to showcase both Split and DataTree, but I fear the complexity of the DataTree in this sample is working against our larger goals of making Flutter on desktop approachable. Would you be ok with taking DataTree out and replacing it with something simpler? The upside is that we get a path to introducing shared preferences to store favorited photos.
| @@ -0,0 +1,194 @@ | |||
| // Copyright 2019 The Chromium Authors. All rights reserved. | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has a different author name than the others. Is it pulled from something else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, it's @DaveShuckerow's code, and lifted and adapted from Flutter DevTool Widget Inspector, if memory serves.
Adding a desktop sample app.