Skip to content

Commit

Permalink
feature: add network availability checker
Browse files Browse the repository at this point in the history
Closes #65
  • Loading branch information
rafamizes authored Dec 3, 2023
1 parent 9c5a3fb commit eb9a599
Show file tree
Hide file tree
Showing 22 changed files with 647 additions and 44 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Network availability checker —
[#65](https://github.com/dartoos-dev/astronomy_picture_of_the_day/issues/65).

## [0.1.2] - 2023-12-02

### Added
Expand Down
5 changes: 5 additions & 0 deletions android/app/.classpath
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="/Users/rafamizes/Library/Android/sdk/sources/android-28/"/>
<classpathentry kind="lib" path="."/>
</classpath>
1 change: 1 addition & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:label="astronomy_picture_of_the_day"
android:name="${applicationName}"
Expand Down
1 change: 1 addition & 0 deletions ios/Flutter/Debug.xcconfig
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
1 change: 1 addition & 0 deletions ios/Flutter/Release.xcconfig
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
44 changes: 44 additions & 0 deletions ios/Podfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '11.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}

def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end

File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end

require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)

flutter_ios_podfile_setup

target 'Runner' do
use_frameworks!
use_modular_headers!

flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end

post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end
14 changes: 14 additions & 0 deletions lib/shared/connectivity/data/drivers/connectivity_driver.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/// Driver for checking the availability of a connection to a data network and
/// the connection status.
abstract interface class ConnectivityDriver {
/// Returns `true` if an active data connection is actually available — the
/// device is not only connected but can also send/receive data over the
/// network. Otherwise, it returns `false`.
///
/// For example, it will return `true` if the device is both connected to a
/// network (Wi-Fi, 3g, 4g, bluetooth, ethernet, etc) and can send/receive
/// data.
///
/// Throws [DriverException] to indicate an operation error.
Future<bool> get hasActiveInternetConnection;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:internet_connection_checker_plus/internet_connection_checker_plus.dart';

import '../../../errors/driver_exception.dart';
import '../../data/drivers/connectivity_driver.dart';

/// [ConnectivityDriver] implementation based on 'connectivity_plus' and
/// 'internet_connection_checker_plus' packages.
///
/// For further information, see:
///
/// - [connectivity_plus](https://pub.dev/packages/connectivity_plus)
/// - [internet_connection_checker_plus](https://pub.dev/packages/internet_connection_checker_plus)
final class ConnectivityDriverImpl implements ConnectivityDriver {
const ConnectivityDriverImpl(
Connectivity connectivity,
InternetConnection internet,
) : _connectivity = connectivity,
_internet = internet;

final Connectivity _connectivity;
final InternetConnection _internet;

@override
Future<bool> get hasActiveInternetConnection async {
try {
final result = await _connectivity.onConnectivityChanged.first;
return result != ConnectivityResult.none &&
await _internet.hasInternetAccess;
} on Exception catch (ex) {
throw DriverException(
'Error while checking connection status',
exception: ex,
);
}
}
}
10 changes: 10 additions & 0 deletions lib/shared/errors/driver_exception.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import 'dart:io';

import 'app_exception.dart';

/// Represents I/O errors thrown by _Driver_ classes.
class DriverException extends AppException implements IOException {
/// Defines [info] as additional information and [exception] as the original
/// thrown exception.
const DriverException(String super.info, {super.exception});
}
1 change: 1 addition & 0 deletions macos/Flutter/Flutter-Debug.xcconfig
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig"
1 change: 1 addition & 0 deletions macos/Flutter/Flutter-Release.xcconfig
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig"
2 changes: 2 additions & 0 deletions macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import FlutterMacOS
import Foundation

import connectivity_plus

func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
}
43 changes: 43 additions & 0 deletions macos/Podfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
platform :osx, '10.14'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}

def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
end

File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
end

require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)

flutter_macos_podfile_setup

target 'Runner' do
use_frameworks!
use_modular_headers!

flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end

post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_macos_build_settings(target)
end
end
2 changes: 2 additions & 0 deletions macos/Runner/DebugProfile.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@
<true/>
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>
2 changes: 2 additions & 0 deletions macos/Runner/Release.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>
106 changes: 104 additions & 2 deletions pubspec.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
args:
dependency: transitive
description:
name: args
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
url: "https://pub.dev"
source: hosted
version: "2.4.2"
async:
dependency: transitive
description:
Expand Down Expand Up @@ -49,6 +57,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.18.0"
connectivity_plus:
dependency: "direct main"
description:
name: connectivity_plus
sha256: "224a77051d52a11fbad53dd57827594d3bd24f945af28bd70bab376d68d437f0"
url: "https://pub.dev"
source: hosted
version: "5.0.2"
connectivity_plus_platform_interface:
dependency: transitive
description:
name: connectivity_plus_platform_interface
sha256: cf1d1c28f4416f8c654d7dc3cd638ec586076255d407cef3ddbdaf178272a71a
url: "https://pub.dev"
source: hosted
version: "1.2.4"
crypto:
dependency: transitive
description:
Expand All @@ -65,6 +89,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.10.1"
dbus:
dependency: transitive
description:
name: dbus
sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac"
url: "https://pub.dev"
source: hosted
version: "0.7.10"
dio:
dependency: "direct main"
description:
Expand Down Expand Up @@ -97,6 +129,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.1"
ffi:
dependency: transitive
description:
name: ffi
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
flutter:
dependency: "direct main"
description: flutter
Expand All @@ -120,6 +160,19 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
http:
dependency: transitive
description:
name: http
sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139
url: "https://pub.dev"
source: hosted
version: "1.1.2"
http_parser:
dependency: transitive
description:
Expand All @@ -128,6 +181,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.2"
internet_connection_checker_plus:
dependency: "direct main"
description:
name: internet_connection_checker_plus
sha256: c62fe6c2a2fe666b5c7b083f591679095e70109ada53ee2a64360a20e4f5ddac
url: "https://pub.dev"
source: hosted
version: "2.1.0"
intl:
dependency: transitive
description:
Expand All @@ -136,6 +197,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.18.1"
js:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.dev"
source: hosted
version: "0.6.7"
lint:
dependency: "direct dev"
description:
Expand Down Expand Up @@ -200,6 +269,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.3.2"
nm:
dependency: transitive
description:
name: nm
sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254"
url: "https://pub.dev"
source: hosted
version: "0.5.0"
path:
dependency: transitive
description:
Expand All @@ -208,6 +285,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.8.3"
petitparser:
dependency: transitive
description:
name: petitparser
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
url: "https://pub.dev"
source: hosted
version: "6.0.2"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8
url: "https://pub.dev"
source: hosted
version: "2.1.7"
result_dart:
dependency: transitive
description:
Expand Down Expand Up @@ -278,7 +371,7 @@ packages:
source: hosted
version: "1.3.2"
uuid:
dependency: "direct main"
dependency: transitive
description:
name: uuid
sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
Expand All @@ -301,5 +394,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.3.0"
xml:
dependency: transitive
description:
name: xml
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
url: "https://pub.dev"
source: hosted
version: "6.5.0"
sdks:
dart: ">=3.2.0-194.0.dev <4.0.0"
dart: ">=3.2.0 <4.0.0"
flutter: ">=3.3.0"
Loading

1 comment on commit eb9a599

@0pdd
Copy link

@0pdd 0pdd commented on eb9a599 Dec 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't able to retrieve PDD puzzles from the code base and submit them to github. If you think that it's a bug on our side, please submit it to yegor256/0pdd:

set -x && set -e && set -o pipefail && cd /tmp/0pdd20231203-14-k33rnl/Z2l0QGdpdGh1Yi5jb206ZGFydG9vcy1kZXYvYXN0cm9ub215X3BpY3R1cmVfb2ZfdGhlX2RheS5naXQ && pdd -v -f /tmp/20231203-1070536-cbrqsj [255]: + set -e + set -o pipefail + cd...

Please, copy and paste this stack trace to GitHub:

Exec::Error
set -x && set -e && set -o pipefail && cd /tmp/0pdd20231203-14-k33rnl/Z2l0QGdpdGh1Yi5jb206ZGFydG9vcy1kZXYvYXN0cm9ub215X3BpY3R1cmVfb2ZfdGhlX2RheS5naXQ && pdd -v -f /tmp/20231203-1070536-cbrqsj [255]:
+ set -e
+ set -o pipefail
+ cd /tmp/0pdd20231203-14-k33rnl/Z2l0QGdpdGh1Yi5jb206ZGFydG9vcy1kZXYvYXN0cm9ub215X3BpY3R1cmVfb2ZfdGhlX2RheS5naXQ
+ pdd -v -f /tmp/20231203-1070536-cbrqsj

My version is 0.23.2
Ruby version is 3.1.4 at x86_64-linux
Reading from root dir /tmp/0pdd20231203-14-k33rnl/Z2l0QGdpdGh1Yi5jb206ZGFydG9vcy1kZXYvYXN0cm9ub215X3BpY3R1cmVfb2ZfdGhlX2RheS5naXQ
ERROR: ERROR (Errno::ENOENT): No such file or directory @ rb_file_s_size - /tmp/0pdd20231203-14-k33rnl/Z2l0QGdpdGh1Yi5jb206ZGFydG9vcy1kZXYvYXN0cm9ub215X3BpY3R1cmVfb2ZfdGhlX2RheS5naXQ/.fvm/flutter_sdk
Exit code is 255

/app/objects/exec.rb:62:in `block (2 levels) in run'
/app/vendor/ruby-3.1.4/lib/ruby/3.1.0/open3.rb:228:in `popen_run'
/app/vendor/ruby-3.1.4/lib/ruby/3.1.0/open3.rb:103:in `popen3'
/app/objects/exec.rb:55:in `block in run'
/app/vendor/bundle/ruby/3.1.0/gems/timeout-0.4.0/lib/timeout.rb:186:in `block in timeout'
/app/vendor/bundle/ruby/3.1.0/gems/timeout-0.4.0/lib/timeout.rb:41:in `handle_timeout'
/app/vendor/bundle/ruby/3.1.0/gems/timeout-0.4.0/lib/timeout.rb:195:in `timeout'
/app/objects/exec.rb:54:in `run'
/app/objects/git_repo.rb:71:in `block in xml'
/app/vendor/ruby-3.1.4/lib/ruby/3.1.0/tempfile.rb:317:in `open'
/app/objects/git_repo.rb:69:in `xml'
/app/objects/puzzles.rb:41:in `deploy'
/app/objects/jobs/job.rb:38:in `proceed'
/app/objects/jobs/job_starred.rb:32:in `proceed'
/app/objects/jobs/job_recorded.rb:31:in `proceed'
/app/objects/jobs/job_emailed.rb:33:in `proceed'
/app/objects/jobs/job_commiterrors.rb:33:in `proceed'
/app/objects/jobs/job_detached.rb:48:in `exclusive'
/app/objects/jobs/job_detached.rb:36:in `block in proceed'
/app/objects/jobs/job_detached.rb:36:in `fork'
/app/objects/jobs/job_detached.rb:36:in `proceed'
/app/0pdd.rb:531:in `process_request'
/app/0pdd.rb:367:in `block in <top (required)>'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1706:in `call'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1706:in `block in compile!'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1019:in `block (3 levels) in route!'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1037:in `route_eval'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1019:in `block (2 levels) in route!'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1068:in `block in process_route'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1066:in `catch'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1066:in `process_route'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1017:in `block in route!'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1014:in `each'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1014:in `route!'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1138:in `block in dispatch!'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1109:in `catch'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1109:in `invoke'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1133:in `dispatch!'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:949:in `block in call!'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1109:in `catch'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1109:in `invoke'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:949:in `call!'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:938:in `call'
/app/vendor/bundle/ruby/3.1.0/gems/rack-2.2.8/lib/rack/deflater.rb:44:in `call'
/app/vendor/bundle/ruby/3.1.0/gems/rack-protection-3.0.6/lib/rack/protection/xss_header.rb:20:in `call'
/app/vendor/bundle/ruby/3.1.0/gems/rack-protection-3.0.6/lib/rack/protection/path_traversal.rb:18:in `call'
/app/vendor/bundle/ruby/3.1.0/gems/rack-protection-3.0.6/lib/rack/protection/json_csrf.rb:28:in `call'
/app/vendor/bundle/ruby/3.1.0/gems/rack-protection-3.0.6/lib/rack/protection/base.rb:53:in `call'
/app/vendor/bundle/ruby/3.1.0/gems/rack-protection-3.0.6/lib/rack/protection/base.rb:53:in `call'
/app/vendor/bundle/ruby/3.1.0/gems/rack-protection-3.0.6/lib/rack/protection/frame_options.rb:33:in `call'
/app/vendor/bundle/ruby/3.1.0/gems/rack-2.2.8/lib/rack/logger.rb:17:in `call'
/app/vendor/bundle/ruby/3.1.0/gems/rack-2.2.8/lib/rack/common_logger.rb:38:in `call'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:261:in `call'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:254:in `call'
/app/vendor/bundle/ruby/3.1.0/gems/rack-2.2.8/lib/rack/head.rb:12:in `call'
/app/vendor/bundle/ruby/3.1.0/gems/rack-2.2.8/lib/rack/method_override.rb:24:in `call'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:219:in `call'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:2018:in `call'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1576:in `block in call'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1792:in `synchronize'
/app/vendor/bundle/ruby/3.1.0/gems/sinatra-3.0.6/lib/sinatra/base.rb:1576:in `call'
/app/vendor/bundle/ruby/3.1.0/gems/rack-2.2.8/lib/rack/handler/webrick.rb:95:in `service'
/app/vendor/bundle/ruby/3.1.0/gems/webrick-1.8.1/lib/webrick/httpserver.rb:140:in `service'
/app/vendor/bundle/ruby/3.1.0/gems/webrick-1.8.1/lib/webrick/httpserver.rb:96:in `run'
/app/vendor/bundle/ruby/3.1.0/gems/webrick-1.8.1/lib/webrick/server.rb:310:in `block in start_thread'

Please sign in to comment.