Skip to content

Commit

Permalink
気象庁による 地震・津波のお知らせ (#529)
Browse files Browse the repository at this point in the history
* fix

* fix

* Merge branch 'feature/jma-bbox' into develop

* add

* add: details view
  • Loading branch information
YumNumm authored Jan 20, 2024
1 parent 269e80c commit 9885c38
Show file tree
Hide file tree
Showing 39 changed files with 737 additions and 588 deletions.
64 changes: 56 additions & 8 deletions lib/core/extension/async_value.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,64 @@
import 'dart:async';
// ignore_for_file: avoid_positional_boolean_parameters

import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

extension AsyncValueExt<T> on AsyncValue<T> {
Future<AsyncValue<T>> guardPlus(
Future<T> Function() future,
) async {
// https://zenn.dev/k9i/articles/b8c333e1bb8b9b
extension AsyncValueX<T> on AsyncValue<T> {
/// guard関数の拡張版
/// 例外時に前回のデータを持たせてエラーを返す
Future<AsyncValue<T>> guardPlus(Future<T> Function() future) async {
try {
return AsyncValue<T>.data(await future());
return AsyncValue.data(await future());
// ignore: avoid_catches_without_on_clauses
} catch (e, st) {
return AsyncValue<T>.error(e, st).copyWithPrevious(this);
} catch (err, stack) {
// 前回のデータを持たせてエラーを返す
return AsyncValue<T>.error(err, stack).copyWithPrevious(this);
}
}

/// when関数の拡張版
///
/// [skipErrorOnHasValue]がtrueの時はデータがある場合のエラーをスキップする
/// ページングの2ページ目以降でエラー時に、取得ずみデータを表示する場合などに使用する
R whenPlus<R>({
bool skipLoadingOnReload = false,
bool skipLoadingOnRefresh = true,
bool skipError = false,
bool skipErrorOnHasValue = false,
required R Function(T data, bool hasError) data,
required R Function(Object error, StackTrace stackTrace) error,
required R Function() loading,
}) {
if (skipErrorOnHasValue) {
if (hasValue && hasError) {
return data(requireValue, true);
}
}

return when(
skipLoadingOnReload: skipLoadingOnReload,
skipLoadingOnRefresh: skipLoadingOnRefresh,
skipError: skipError,
data: (d) => data(d, hasError),
error: error,
loading: loading,
);
}

/// エラー時にスナックバーを表示する
void showSnackbarOnError(
BuildContext context, {
String defaultMessage = 'エラーが発生しました',
}) {
if (!isLoading && hasError) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
error!.toString(),
),
),
);
}
}
}
56 changes: 36 additions & 20 deletions lib/core/foundation/result.dart
Original file line number Diff line number Diff line change
@@ -1,27 +1,43 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

part 'result.freezed.dart';
/// sealed classに準拠したResultクラスを生成
sealed class Result<S, E extends Exception> {
const Result();

@freezed
sealed class Result<T, R> with _$Result<T, R> {
const Result._();
const factory Result.success(T value) = Success<T, R>;
const factory Result.failure(R error) = Failure<T, R>;
static Future<Result<V, Exception>> capture<V>(
FutureOr<V> Function() fn,
) async {
try {
return Success(await fn.call());
} on Exception catch (e, stackTrace) {
return Failure(e, stackTrace);
}
}

T? get valueOrNull => when(
success: (value) => value,
failure: (_) => null,
);
static Future<Result<V, E>> captureSelected<V, E extends Exception>(
FutureOr<V> Function() fn,
) async {
try {
return Success(await fn.call());
} on E catch (e, stackTrace) {
return Failure(e, stackTrace);
}
}

R? get errorOrNull => when(
success: (_) => null,
failure: (error) => error,
);
static Result<V, Exception> success<V>(V value) => Success(value);
static Result<V, Exception> failure<V>(Exception exception) =>
Failure(exception);
}

bool get isSuccess => when(
success: (_) => true,
failure: (_) => false,
);
/// Resultクラスに準拠したSuccessクラス
final class Success<S, E extends Exception> extends Result<S, E> {
const Success(this.value);
final S value;
}

bool get isFailure => !isSuccess;
/// Resultクラスに準拠したFailureクラス
final class Failure<S, E extends Exception> extends Result<S, E> {
const Failure(this.exception, [this.stackTrace]);
final E exception;
final StackTrace? stackTrace;
}
Loading

0 comments on commit 9885c38

Please sign in to comment.