-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Cleanup dependencies into separate classes.
- Loading branch information
Showing
25 changed files
with
288 additions
and
216 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,18 @@ | ||
import 'dart:async'; | ||
|
||
import 'package:flutter/foundation.dart' as foundation; | ||
import 'package:flutter/widgets.dart'; | ||
import 'package:flutter_starter/prelude/async_compute.dart'; | ||
import 'package:flutter_starter/prelude/http.dart' as http; | ||
import 'package:flutter/widgets.dart' as widgets; | ||
import 'package:flutter_starter/networking/async_compute.dart'; | ||
import 'package:flutter_starter/networking/http_client_provider.dart'; | ||
import 'package:flutter_starter/prelude/time_source.dart'; | ||
import 'package:http/http.dart'; | ||
import 'package:provider/provider.dart'; | ||
|
||
abstract class AppDependencies implements http.HttpClientProvider, AsyncCompute, TimeSource {} | ||
|
||
final class DefaultAppDependencies implements AppDependencies { | ||
@override | ||
T withHttpClient<T>(T Function(Client) block) { | ||
final client = Client(); | ||
try { | ||
return block(client); | ||
} finally { | ||
client.close(); | ||
} | ||
} | ||
|
||
@override | ||
Future<R> compute<M, R>(FutureOr<R> Function(M) callback, M message, {String? debugLabel}) { | ||
return foundation.compute<M, R>(callback, message, debugLabel: debugLabel); | ||
} | ||
final class AppDependencies { | ||
final HttpClientProvider httpClientProvider; | ||
final AsyncCompute asyncCompute; | ||
final TimeSource timeSource; | ||
|
||
@override | ||
DateTime now() => DateTime.now(); | ||
AppDependencies( | ||
{required this.httpClientProvider, required this.asyncCompute, required this.timeSource}); | ||
} | ||
|
||
extension AppDependenciesGetter on BuildContext { | ||
extension AppDependenciesGetter on widgets.BuildContext { | ||
AppDependencies appDependencies() => Provider.of<AppDependencies>(this, listen: false); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import 'dart:async'; | ||
|
||
import 'package:flutter/foundation.dart' as foundation; | ||
|
||
abstract class AsyncCompute { | ||
Future<R> compute<M, R>(FutureOr<R> Function(M) callback, M message, {String? debugLabel}); | ||
} | ||
|
||
class FoundationAsyncCompute implements AsyncCompute { | ||
@override | ||
Future<R> compute<M, R>(FutureOr<R> Function(M) callback, M message, {String? debugLabel}) { | ||
return foundation.compute<M, R>(callback, message, debugLabel: debugLabel); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import 'package:flutter_starter/prelude/result.dart'; | ||
import 'package:http/http.dart'; | ||
import 'package:logger/logger.dart'; | ||
|
||
import 'async_compute.dart'; | ||
import 'http_error.dart'; | ||
import 'json_decoder.dart'; | ||
|
||
enum HttpMethod { | ||
get, | ||
post, | ||
put, | ||
delete; | ||
|
||
@override | ||
String toString() => switch (this) { | ||
get => 'GET', | ||
post => 'POST', | ||
put => 'PUT', | ||
delete => 'DELETE', | ||
}; | ||
} | ||
|
||
typedef HttpResult<T> = Result<T, HttpError>; | ||
typedef HttpFuture<T> = Future<HttpResult<T>>; | ||
|
||
extension SendRequest on Client { | ||
HttpFuture<Response> sendRequest(HttpMethod method, Uri url) async { | ||
try { | ||
final request = Request(method.toString(), url); | ||
final streamedResponse = await send(request); | ||
final response = await Response.fromStream(streamedResponse); | ||
|
||
return Ok(response); | ||
} on Exception catch (e) { | ||
return Err(HttpConnectionError(e)); | ||
} | ||
} | ||
} | ||
|
||
extension ResponseHandling on HttpResult<Response> { | ||
HttpResult<Response> expectStatusCode(int expected) => flatMapOk((response) { | ||
if (response.statusCode == expected) { | ||
return Ok(response); | ||
} else { | ||
return Err(HttpUnexpectedStatusCodeError(expected, response.statusCode)); | ||
} | ||
}); | ||
|
||
HttpFuture<T> tryParseJson<T>(AsyncCompute async, JsonDecode<T> decode) async { | ||
return switch (this) { | ||
Ok(value: final response) => async.compute( | ||
(response) { | ||
try { | ||
final jsonObject = JsonDecoder.fromString(response.body); | ||
final object = decode(jsonObject); | ||
return Ok(object); | ||
} on TypeError catch (e) { | ||
_logger.e('Failed to parse json: ${response.body}', e); | ||
return Err(HttpDeserializationError(e, response.body)); | ||
} | ||
}, | ||
response, | ||
), | ||
Err(error: final error) => Future.value(Err(error)), | ||
}; | ||
} | ||
} | ||
|
||
final _logger = Logger(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import 'package:http/http.dart'; | ||
|
||
abstract class HttpClientProvider { | ||
T withHttpClient<T>(T Function(Client client) block); | ||
} | ||
|
||
class ConcreteHttpClientProvider implements HttpClientProvider { | ||
@override | ||
T withHttpClient<T>(T Function(Client) block) { | ||
final client = Client(); | ||
try { | ||
return block(client); | ||
} finally { | ||
client.close(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
sealed class HttpError {} | ||
|
||
final class HttpConnectionError implements HttpError { | ||
const HttpConnectionError(this.exception); | ||
|
||
final Exception exception; | ||
} | ||
|
||
final class HttpUnexpectedStatusCodeError implements HttpError { | ||
const HttpUnexpectedStatusCodeError(this.expected, this.actual); | ||
|
||
final int expected; | ||
final int actual; | ||
} | ||
|
||
final class HttpDeserializationError implements HttpError { | ||
const HttpDeserializationError(this.error, this.responseBody); | ||
|
||
final TypeError error; | ||
final String responseBody; | ||
} | ||
|
||
extension HttpErrorMessage on HttpError { | ||
String message() => switch (this) { | ||
HttpConnectionError() => 'There was an error connecting', | ||
HttpUnexpectedStatusCodeError() => 'Unexpected response from api', | ||
HttpDeserializationError() => 'Failed to parse response', | ||
}; | ||
} |
File renamed without changes.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.