Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion lib/constants/brew_exe.dart

This file was deleted.

8 changes: 8 additions & 0 deletions lib/constants/constants.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class Constants {
const Constants._();

static const brewExecutable = 'brew';
static const brewInfoCmd = 'info';
static const brewListCmd = 'list';
static const brewUninstallCmd = 'uninstall';
}
40 changes: 40 additions & 0 deletions lib/exceptions/exceptions.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
abstract class BrewException {
String get message;
}

class ProcessLaunchException implements BrewException {
ProcessLaunchException(this.args, this.error);

final List<String> args;
final Object error;

@override
String get message => 'Cannot launch brew with args $args : $error';
}

class ProcessStdoutReadingException implements BrewException {
ProcessStdoutReadingException(this.error);

final Object error;

@override
String get message => 'Cannot parse process stdout : $error';
}

class ProcessStdoutLastException implements BrewException {
ProcessStdoutLastException(this.error);

final Object error;

@override
String get message => 'Cannot read last from stdout : $error';
}

class ProcessStdoutOnDoneException implements BrewException {
ProcessStdoutOnDoneException(this.error);

final Object error;

@override
String get message => 'Cannot wait for stdout to complete : $error';
}
4 changes: 2 additions & 2 deletions lib/features/commands/data/commands_repository.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'dart:async';
import 'dart:io';

import 'package:brew_flutter/constants/brew_exe.dart';
import 'package:brew_flutter/constants/constants.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

final brewCommandsRepositoryProvider =
Expand All @@ -12,7 +12,7 @@ class BrewCommandsRepository {
late Process process;

Future<void> launch(List<String> args) async {
process = await Process.start(kBrewExecutable, args);
process = await Process.start(Constants.brewExecutable, args);
stdout = process.stdout.map(String.fromCharCodes);
}

Expand Down
10 changes: 5 additions & 5 deletions lib/features/commands/state/command_state.freezed.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 14 additions & 7 deletions lib/features/info/data/info_repository.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import 'dart:io';

import 'package:brew_flutter/constants/brew_exe.dart';
import 'package:brew_flutter/constants/constants.dart';
import 'package:brew_flutter/exceptions/exceptions.dart';
import 'package:brew_flutter/features/info/model/package_info.dart';
import 'package:brew_flutter/utils/process.dart';
import 'package:fpdart/fpdart.dart';

Future<PackageInfo> runBrewInfo(String package) async {
final process = await Process.start(kBrewExecutable, ['info', package]);
return PackageInfo.fromRaw(
await process.stdout.map(String.fromCharCodes).join('\n'),
);
}
TaskEither<BrewException, PackageInfo> brewInfoTE(String package) =>
startProcessTask([Constants.brewInfoCmd, package])
.flatMap(_processStdoutTE)
.map(PackageInfo.fromRaw); // IMPURE

TaskEither<BrewException, String> _processStdoutTE(Process process) =>
TaskEither.tryCatch(
() => process.stdout.map(String.fromCharCodes).join('\n'),
(err, __) => ProcessStdoutReadingException(err),
);
4 changes: 3 additions & 1 deletion lib/features/info/model/package_info.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
typedef PackageName = String;

class PackageInfo {
PackageInfo({
required this.name,
Expand All @@ -24,7 +26,7 @@ class PackageInfo {
);
}

final String name;
final PackageName name;
final String version;
final String description;
final String url;
Expand Down
25 changes: 23 additions & 2 deletions lib/features/info/state/info_provider.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
import 'package:brew_flutter/features/info/data/info_repository.dart';
import 'package:brew_flutter/features/info/model/package_info.dart';
import 'package:brew_flutter/features/info/state/info_state.dart';
import 'package:fpdart/fpdart.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

final packageInfoProvider = FutureProvider.family<PackageInfo, String>(
(_, package) => runBrewInfo(package),
class PackageInfoState extends StateNotifier<InfoState> {
PackageInfoState(this.packageName) : super(const InfoState.loading()) {
init();
}

final PackageName packageName;

Future<Unit> init() async {
state = const InfoState.loading();
final infoTask = brewInfoTE(packageName);
state = (await infoTask.run()).match(
(error) => InfoState.error(error.message),
InfoState.success,
);
return unit;
}
}

final packageInfoProvider =
StateNotifierProviderFamily<PackageInfoState, InfoState, PackageName>(
(_, packageName) => PackageInfoState(packageName),
);
11 changes: 11 additions & 0 deletions lib/features/info/state/info_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import 'package:brew_flutter/features/info/model/package_info.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

part 'info_state.freezed.dart';

@freezed
class InfoState with _$InfoState {
const factory InfoState.loading() = LoadingInfoState;
const factory InfoState.error(String string) = ErrorInfoState;
const factory InfoState.success(PackageInfo info) = SuccessInfoState;
}
Loading