diff --git a/README.md b/README.md
index 2267f342..bbc0307c 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,8 @@ Vernet - Network Analyzer and Monitoring Tool
[![F-Droid](https://img.shields.io/f-droid/v/org.fsociety.vernet)](https://f-droid.org/packages/org.fsociety.vernet)
[![GitHub release (including pre-releases)](https://img.shields.io/github/v/release/git-elliot/vernet?include_prereleases)](https://github.com/git-elliot/vernet/releases/latest)
![GitHub repo size](https://img.shields.io/github/repo-size/git-elliot/vernet)
+![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/osociety/vernet/total)
+![Liberapay receiving](https://img.shields.io/liberapay/receives/opensociety)
## Features
@@ -15,9 +17,11 @@ Vernet - Network Analyzer and Monitoring Tool
## Screenshots
-|Vernet|Home|Devices|Open Ports|Dark Home|Settings|
-|-|-|-|-|-|-|
-|||||||
+|Vernet|Home|Devices|Open Ports|
+|-|-|-|-|
+|||||
+|Ping|DNS|Reverse DNS|Settings|
+|||||
## Download
diff --git a/android/app/build.gradle b/android/app/build.gradle
index cf2069f3..d45a3de1 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -41,6 +41,7 @@ android {
targetSdkVersion 35
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
+ multiDexEnabled true
}
signingConfigs {
release {
@@ -83,6 +84,7 @@ android {
namespace "org.fsociety.vernet"
compileOptions {
+ coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
@@ -91,6 +93,12 @@ android {
}
}
+dependencies {
+ coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.2'
+ implementation 'androidx.window:window:1.0.0'
+ implementation 'androidx.window:window-java:1.0.0'
+}
+
flutter {
source '../..'
}
\ No newline at end of file
diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro
new file mode 100644
index 00000000..f8768e4b
--- /dev/null
+++ b/android/app/proguard-rules.pro
@@ -0,0 +1,27 @@
+## Gson rules
+# Gson uses generic type information stored in a class file when working with fields. Proguard
+# removes such information by default, so configure it to keep all of it.
+-keepattributes Signature
+
+# For using GSON @Expose annotation
+-keepattributes *Annotation*
+
+# Gson specific classes
+-dontwarn sun.misc.**
+#-keep class com.google.gson.stream.** { *; }
+
+# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory,
+# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
+-keep class * extends com.google.gson.TypeAdapter
+-keep class * implements com.google.gson.TypeAdapterFactory
+-keep class * implements com.google.gson.JsonSerializer
+-keep class * implements com.google.gson.JsonDeserializer
+
+# Prevent R8 from leaving Data object members always null
+-keepclassmembers,allowobfuscation class * {
+ @com.google.gson.annotations.SerializedName ;
+}
+
+# Retain generic signatures of TypeToken and its subclasses with R8 version 3.0 and higher.
+-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
+-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken
\ No newline at end of file
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index d921e5a1..10557b2a 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -3,6 +3,8 @@
+
+
diff --git a/android/app/src/main/res/drawable/app_icon.png b/android/app/src/main/res/drawable/app_icon.png
new file mode 100644
index 00000000..f6574bba
Binary files /dev/null and b/android/app/src/main/res/drawable/app_icon.png differ
diff --git a/android/app/src/main/res/raw/keep.xml b/android/app/src/main/res/raw/keep.xml
new file mode 100644
index 00000000..18b75e3e
--- /dev/null
+++ b/android/app/src/main/res/raw/keep.xml
@@ -0,0 +1,3 @@
+
+
\ No newline at end of file
diff --git a/android/fastlane/metadata/android/en-US/changelogs/27.txt b/android/fastlane/metadata/android/en-US/changelogs/27.txt
new file mode 100644
index 00000000..c7e75daa
--- /dev/null
+++ b/android/fastlane/metadata/android/en-US/changelogs/27.txt
@@ -0,0 +1 @@
+Bug fix for scan for devices not working
\ No newline at end of file
diff --git a/android/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png b/android/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png
index 6cda6a70..ec7c9ab5 100644
Binary files a/android/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png and b/android/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png differ
diff --git a/android/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png b/android/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png
index 534bc198..0a5e40c3 100644
Binary files a/android/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png and b/android/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png differ
diff --git a/android/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png b/android/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png
index abf8b7ec..5265769b 100644
Binary files a/android/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png and b/android/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png differ
diff --git a/android/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png b/android/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png
index 20a4d229..6e680843 100644
Binary files a/android/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png and b/android/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png differ
diff --git a/android/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png b/android/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png
index 765bf163..128db8be 100644
Binary files a/android/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png and b/android/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png differ
diff --git a/android/fastlane/metadata/android/en-US/images/phoneScreenshots/6.png b/android/fastlane/metadata/android/en-US/images/phoneScreenshots/6.png
index a3e1c988..af516d8f 100644
Binary files a/android/fastlane/metadata/android/en-US/images/phoneScreenshots/6.png and b/android/fastlane/metadata/android/en-US/images/phoneScreenshots/6.png differ
diff --git a/android/fastlane/metadata/android/en-US/images/phoneScreenshots/7.png b/android/fastlane/metadata/android/en-US/images/phoneScreenshots/7.png
index 205202f7..30b7f216 100644
Binary files a/android/fastlane/metadata/android/en-US/images/phoneScreenshots/7.png and b/android/fastlane/metadata/android/en-US/images/phoneScreenshots/7.png differ
diff --git a/android/fastlane/metadata/android/en-US/images/phoneScreenshots/8.png b/android/fastlane/metadata/android/en-US/images/phoneScreenshots/8.png
index 44d5c3e2..e64cada6 100644
Binary files a/android/fastlane/metadata/android/en-US/images/phoneScreenshots/8.png and b/android/fastlane/metadata/android/en-US/images/phoneScreenshots/8.png differ
diff --git a/assets/app_icon.png b/assets/app_icon.png
new file mode 100644
index 00000000..f6574bba
Binary files /dev/null and b/assets/app_icon.png differ
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 366ef86c..7c2e90f7 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -6,8 +6,16 @@ PODS:
- Flutter
- flutter_isolate (0.0.1):
- Flutter
+ - flutter_local_notifications (0.0.1):
+ - Flutter
- flutter_native_splash (0.0.1):
- Flutter
+ - flutter_timezone (0.0.1):
+ - Flutter
+ - in_app_review (0.2.0):
+ - Flutter
+ - isar_flutter_libs (1.0.0):
+ - Flutter
- network_info_plus (0.0.1):
- Flutter
- nsd_ios (0.0.1):
@@ -30,7 +38,11 @@ DEPENDENCIES:
- Flutter (from `Flutter`)
- flutter_icmp_ping (from `.symlinks/plugins/flutter_icmp_ping/ios`)
- flutter_isolate (from `.symlinks/plugins/flutter_isolate/ios`)
+ - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
+ - flutter_timezone (from `.symlinks/plugins/flutter_timezone/ios`)
+ - in_app_review (from `.symlinks/plugins/in_app_review/ios`)
+ - isar_flutter_libs (from `.symlinks/plugins/isar_flutter_libs/ios`)
- network_info_plus (from `.symlinks/plugins/network_info_plus/ios`)
- nsd_ios (from `.symlinks/plugins/nsd_ios/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
@@ -48,8 +60,16 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flutter_icmp_ping/ios"
flutter_isolate:
:path: ".symlinks/plugins/flutter_isolate/ios"
+ flutter_local_notifications:
+ :path: ".symlinks/plugins/flutter_local_notifications/ios"
flutter_native_splash:
:path: ".symlinks/plugins/flutter_native_splash/ios"
+ flutter_timezone:
+ :path: ".symlinks/plugins/flutter_timezone/ios"
+ in_app_review:
+ :path: ".symlinks/plugins/in_app_review/ios"
+ isar_flutter_libs:
+ :path: ".symlinks/plugins/isar_flutter_libs/ios"
network_info_plus:
:path: ".symlinks/plugins/network_info_plus/ios"
nsd_ios:
@@ -70,14 +90,18 @@ SPEC CHECKSUMS:
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_icmp_ping: 2b159955eee0c487c766ad83fec224ae35e7c935
flutter_isolate: 0edf5081826d071adf21759d1eb10ff5c24503b5
+ flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086
flutter_native_splash: edf599c81f74d093a4daf8e17bd7a018854bc778
+ flutter_timezone: ffb07bdad3c6276af8dada0f11978d8a1f8a20bb
+ in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d
+ isar_flutter_libs: b69f437aeab9c521821c3f376198c4371fa21073
network_info_plus: 6d0c3eb8367b8164fa3fb0c19875e3f59d49697f
nsd_ios: 8c37babdc6538e3350dbed3a52674d2edde98173
package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85
- path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
+ path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
- shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
- url_launcher_ios: 6116280ddcfe98ab8820085d8d76ae7449447586
+ shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
+ url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
PODFILE CHECKSUM: c4c93c5f6502fe2754f48404d3594bf779584011
diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift
index 70693e4a..a527abb7 100644
--- a/ios/Runner/AppDelegate.swift
+++ b/ios/Runner/AppDelegate.swift
@@ -1,12 +1,15 @@
import UIKit
import Flutter
-@UIApplicationMain
+@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
+ if #available(iOS 10.0, *) {
+ UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
+ }
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
diff --git a/lib/main.dart b/lib/main.dart
index f7e72c56..4ee460ef 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart';
-import 'package:network_info_plus/network_info_plus.dart';
import 'package:network_tools_flutter/network_tools_flutter.dart';
import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart';
@@ -9,10 +8,11 @@ import 'package:vernet/helper/app_settings.dart';
import 'package:vernet/helper/consent_loader.dart';
import 'package:vernet/injection.dart';
import 'package:vernet/pages/home_page.dart';
+import 'package:vernet/pages/host_scan_page/host_scan_page.dart';
import 'package:vernet/pages/location_consent_page.dart';
import 'package:vernet/pages/settings_page.dart';
import 'package:vernet/providers/dark_theme_provider.dart';
-import 'package:vernet/services/impls/device_scanner_service.dart';
+import 'package:vernet/repository/notification_service.dart';
AppSettings appSettings = AppSettings.instance;
Future main() async {
@@ -27,12 +27,17 @@ Future main() async {
final bool allowed = await ConsentLoader.isConsentPageShown();
await appSettings.load();
+ await NotificationService.initNotification();
+
runApp(MyApp(allowed));
FlutterNativeSplash.remove();
}
class MyApp extends StatefulWidget {
const MyApp(this.allowed, {super.key});
+ static final GlobalKey navigatorKey =
+ GlobalKey();
+ // static const Color mainColor = Colors.deepPurple;
final bool allowed;
@@ -46,21 +51,8 @@ class _MyAppState extends State {
@override
void initState() {
super.initState();
+ NotificationService.grantPermissions();
getCurrentAppTheme();
- startScanOnStartup();
- }
-
- Future startScanOnStartup() async {
- if (appSettings.runScanOnStartup) {
- final ip = await NetworkInfo().getWifiIP();
- final gatewayIp = appSettings.customSubnet.isNotEmpty
- ? appSettings.customSubnet
- : await NetworkInfo().getWifiGatewayIP();
- final subnet = gatewayIp!.substring(0, gatewayIp.lastIndexOf('.'));
- getIt()
- .startNewScan(subnet, ip!, gatewayIp)
- .listen((device) {});
- }
}
Future getCurrentAppTheme() async {
@@ -77,18 +69,40 @@ class _MyAppState extends State {
child: Consumer(
builder: (BuildContext context, value, Widget? child) {
return MaterialApp(
+ navigatorKey: MyApp.navigatorKey,
+ initialRoute: '/',
+ onGenerateRoute: (settings) {
+ switch (settings.name) {
+ case '/':
+ return MaterialPageRoute(
+ builder: (context) => homePage,
+ );
+
+ case '/hostscan':
+ return MaterialPageRoute(
+ builder: (context) {
+ return HostScanPage();
+ },
+ );
+
+ default:
+ assert(false, 'Page ${settings.name} not found');
+ return null;
+ }
+ },
title: 'Vernet',
theme: themeChangeProvider.darkTheme
? ThemeData.dark()
: ThemeData.light(),
- home: widget.allowed
- ? const TabBarPage()
- : const LocationConsentPage(),
+ home: homePage,
);
},
),
);
}
+
+ Widget get homePage =>
+ widget.allowed ? const TabBarPage() : const LocationConsentPage();
}
class TabBarPage extends StatefulWidget {
diff --git a/lib/models/wifi_info.dart b/lib/models/wifi_info.dart
index 966504d3..ba0c583e 100644
--- a/lib/models/wifi_info.dart
+++ b/lib/models/wifi_info.dart
@@ -1,5 +1,12 @@
class WifiInfo {
- WifiInfo(this._ip, this._bssid, this._name, this.unknown);
+ WifiInfo(
+ this._ip,
+ this._bssid,
+ this._name,
+ this.unknown,
+ this.gatewayIp,
+ this.isLocationOn,
+ );
static Set defaultBSSID = {'00:00:00:00:00:00'};
final String? _bssid;
@@ -7,6 +14,10 @@ class WifiInfo {
final String? _name;
bool unknown;
String get ip => _ip ?? 'x.x.x.x';
+ int totalDevices = 0;
+ final String gatewayIp;
+ final bool isLocationOn;
+ String get subnet => gatewayIp.substring(0, gatewayIp.lastIndexOf('.'));
static const String noWifiName = 'Wi-Fi';
diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart
index 86f3953e..f33b6db1 100644
--- a/lib/pages/home_page.dart
+++ b/lib/pages/home_page.dart
@@ -5,7 +5,9 @@ import 'package:network_info_plus/network_info_plus.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:vernet/api/isp_loader.dart';
import 'package:vernet/helper/utils_helper.dart';
+import 'package:vernet/injection.dart';
import 'package:vernet/main.dart';
+import 'package:vernet/models/isar/device.dart';
import 'package:vernet/models/wifi_info.dart';
import 'package:vernet/pages/dns/dns_page.dart';
import 'package:vernet/pages/dns/reverse_dns_page.dart';
@@ -13,8 +15,11 @@ import 'package:vernet/pages/host_scan_page/host_scan_page.dart';
import 'package:vernet/pages/network_troubleshoot/port_scan_page.dart';
import 'package:vernet/pages/ping_page/ping_page.dart';
import 'package:vernet/providers/internet_provider.dart';
+import 'package:vernet/repository/notification_service.dart';
+import 'package:vernet/services/impls/device_scanner_service.dart';
import 'package:vernet/ui/adaptive/adaptive_list.dart';
import 'package:vernet/ui/custom_tile.dart';
+import 'package:vernet/values/strings.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@@ -25,9 +30,13 @@ class HomePage extends StatefulWidget {
class _WifiDetailState extends State {
WifiInfo? _wifiInfo;
- bool _location = false;
+ bool scanRunning = false;
+ Set devices = {};
- Future _getWifiInfo() async {
+ Future _getWifiInfo() async {
+ if (_wifiInfo != null) {
+ return _wifiInfo;
+ }
if (Platform.isAndroid) {
await Permission.location.request();
}
@@ -35,23 +44,83 @@ class _WifiDetailState extends State {
final wifiIP = await NetworkInfo().getWifiIP();
final wifiBSSID = await NetworkInfo().getWifiBSSID();
final wifiName = await NetworkInfo().getWifiName();
+ final gatewayIp = appSettings.customSubnet.isNotEmpty
+ ? appSettings.customSubnet
+ : await NetworkInfo().getWifiGatewayIP() ?? '';
+ final bool isLocationOn = (Platform.isAndroid || Platform.isIOS) &&
+ await Permission.location.serviceStatus.isEnabled;
+ _wifiInfo = WifiInfo(
+ wifiIP,
+ wifiBSSID,
+ wifiName,
+ wifiName == null,
+ gatewayIp,
+ isLocationOn,
+ );
- setState(() {
- _wifiInfo = WifiInfo(wifiIP, wifiBSSID, wifiName, wifiName == null);
- });
- if (Platform.isAndroid || Platform.isIOS) {
- Permission.location.serviceStatus.isEnabled.then(
- (value) => setState(() {
- _location = value;
- }),
- );
+ if (appSettings.runScanOnStartup) {
+ getIt()
+ .startNewScan(_wifiInfo!.subnet, wifiIP!, gatewayIp)
+ .listen((device) {
+ if (mounted) {
+ setState(() {
+ scanRunning = true;
+ devices.add(device);
+ });
+ }
+ }).onDone(() async {
+ if (mounted) {
+ setState(() {
+ scanRunning = false;
+ });
+ }
+ await NotificationService.showNotificationWithActions();
+ });
}
+
+ return _wifiInfo;
+ }
+
+ void _configureSelectNotificationSubject() {
+ NotificationService.selectNotificationStream.stream
+ .listen((String? payload) async {
+ await Navigator.of(context).pushNamedAndRemoveUntil(
+ '/hostscan',
+ ModalRoute.withName('/'),
+ );
+ });
+ }
+
+ @override
+ void dispose() {
+ NotificationService.selectNotificationStream.close();
+ super.dispose();
}
@override
void initState() {
super.initState();
- _getWifiInfo();
+ _configureSelectNotificationSubject();
+ }
+
+ Widget _getDeviceCountWidget() {
+ if (appSettings.runScanOnStartup) {
+ return Row(
+ children: [
+ Text(
+ '${devices.length} devices ${scanRunning ? 'found' : 'connected'}',
+ ),
+ const SizedBox(
+ width: 8,
+ ),
+ if (scanRunning)
+ const CircularProgressIndicator.adaptive()
+ else
+ const SizedBox(),
+ ],
+ );
+ }
+ return const SizedBox();
}
@override
@@ -60,19 +129,24 @@ class _WifiDetailState extends State {
child: Column(
children: [
Card(
- //todo: replace this widget by future builder
- child: _wifiInfo == null
- ? const CircularProgressIndicator.adaptive()
- : AdaptiveListTile(
+ child: FutureBuilder(
+ future: _getWifiInfo(),
+ builder: (
+ BuildContext context,
+ AsyncSnapshot snapshot,
+ ) {
+ if (snapshot.hasData && snapshot.data != null) {
+ final wifiInfo = snapshot.data;
+ return AdaptiveListTile(
minVerticalPadding: 10,
leading: const Icon(Icons.router),
- title: Text(_wifiInfo!.name),
+ title: Text(wifiInfo!.name),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Text('Connected to ${_wifiInfo!.bssid}'),
+ Text('Connected to ${wifiInfo.bssid}'),
const SizedBox(height: 5),
- if (_location)
+ if (wifiInfo.isLocationOn)
const SizedBox()
else
Text(
@@ -87,16 +161,24 @@ class _WifiDetailState extends State {
),
const Divider(height: 3),
const SizedBox(height: 10),
- ElevatedButton(
- onPressed: () {
- Navigator.push(
- context,
- MaterialPageRoute(
- builder: (context) => HostScanPage(),
- ),
- );
- },
- child: const Text('Scan for devices'),
+ Row(
+ children: [
+ _getDeviceCountWidget(),
+ const SizedBox(
+ width: 4,
+ ),
+ ElevatedButton(
+ onPressed: () {
+ Navigator.push(
+ context,
+ MaterialPageRoute(
+ builder: (context) => HostScanPage(),
+ ),
+ );
+ },
+ child: const Text(StringValue.hostScanPageTitle),
+ ),
+ ],
),
],
),
@@ -106,7 +188,14 @@ class _WifiDetailState extends State {
_getWifiInfo();
},
),
- ),
+ );
+ } else if (snapshot.hasError) {
+ return const Text("Unable to fetch WiFi details");
+ } else {
+ return const CircularProgressIndicator.adaptive();
+ }
+ },
+ ),
),
Card(
child: AdaptiveListTile(
diff --git a/lib/pages/host_scan_page/host_scan_bloc/host_scan_bloc.dart b/lib/pages/host_scan_page/host_scan_bloc/host_scan_bloc.dart
index a59629d0..4b873319 100644
--- a/lib/pages/host_scan_page/host_scan_bloc/host_scan_bloc.dart
+++ b/lib/pages/host_scan_page/host_scan_bloc/host_scan_bloc.dart
@@ -12,6 +12,7 @@ import 'package:vernet/main.dart';
import 'package:vernet/models/device_in_the_network.dart';
import 'package:vernet/models/isar/device.dart';
import 'package:vernet/models/isar/scan.dart';
+import 'package:vernet/repository/notification_service.dart';
import 'package:vernet/repository/scan_repository.dart';
import 'package:vernet/services/impls/device_scanner_service.dart';
@@ -49,11 +50,7 @@ class HostScanBloc extends Bloc {
deviceInTheNetworkList.clear();
mDnsDevices.clear();
emit(const HostScanState.loadInProgress());
- ip = await NetworkInfo().getWifiIP();
- gatewayIp = appSettings.customSubnet.isNotEmpty
- ? appSettings.customSubnet
- : await NetworkInfo().getWifiGatewayIP();
- subnet = gatewayIp!.substring(0, gatewayIp!.lastIndexOf('.'));
+ await initializeWifiParameters(emit);
if (appSettings.runScanOnStartup) {
add(const HostScanEvent.loadScan());
} else {
@@ -61,6 +58,23 @@ class HostScanBloc extends Bloc {
}
}
+ Future initializeWifiParameters(Emitter emit) async {
+ final wifiGatewayIP = await NetworkInfo().getWifiGatewayIP();
+ if (appSettings.customSubnet.isNotEmpty) {
+ gatewayIp = appSettings.customSubnet;
+ } else if (wifiGatewayIP != null) {
+ gatewayIp = wifiGatewayIP;
+ } else {
+ // NetworkInfo().getWifiGatewayIP() is null on android 35, so fail-safe
+ // to NetworkInfo().getWifiIP()
+ gatewayIp = ip = await NetworkInfo().getWifiIP();
+ }
+ if (gatewayIp == null) {
+ emit(const HostScanState.error());
+ }
+ subnet = gatewayIp!.substring(0, gatewayIp!.lastIndexOf('.'));
+ }
+
Future _startNewScanBuiltInIsolate(
StartNewScan event,
Emitter emit,
@@ -75,6 +89,7 @@ class HostScanBloc extends Bloc {
emit(HostScanState.foundNewDevice(devices));
}
+ await NotificationService.showNotificationWithActions();
emit(HostScanState.loadSuccess(devices));
}
diff --git a/lib/pages/host_scan_page/host_scan_page.dart b/lib/pages/host_scan_page/host_scan_page.dart
index e40b6c58..2a7e7440 100644
--- a/lib/pages/host_scan_page/host_scan_page.dart
+++ b/lib/pages/host_scan_page/host_scan_page.dart
@@ -3,13 +3,14 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:vernet/injection.dart';
import 'package:vernet/pages/host_scan_page/host_scan_bloc/host_scan_bloc.dart';
import 'package:vernet/pages/host_scan_page/widgets/host_scan_widget.dart';
+import 'package:vernet/values/strings.dart';
class HostScanPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
- title: const Text('Scan for Devices'),
+ title: const Text(StringValue.hostScanPageTitle),
),
body: BlocProvider(
create: (context) =>
diff --git a/lib/repository/device_repository.dart b/lib/repository/device_repository.dart
index 1b9d08da..bfc9d2ba 100644
--- a/lib/repository/device_repository.dart
+++ b/lib/repository/device_repository.dart
@@ -49,4 +49,9 @@ class DeviceRepository extends IsarRepository {
.build()
.watch(fireImmediately: true);
}
+
+ Future countByScanId(int scanId) async {
+ final deviceDB = await _database.open();
+ return deviceDB!.devices.filter().scanIdEqualTo(scanId).count();
+ }
}
diff --git a/lib/repository/notification_service.dart b/lib/repository/notification_service.dart
new file mode 100644
index 00000000..48abb005
--- /dev/null
+++ b/lib/repository/notification_service.dart
@@ -0,0 +1,238 @@
+import 'dart:async';
+import 'dart:io';
+
+import 'package:flutter/foundation.dart';
+import 'package:flutter_local_notifications/flutter_local_notifications.dart';
+import 'package:flutter_timezone/flutter_timezone.dart';
+import 'package:timezone/data/latest_all.dart' as tz;
+import 'package:timezone/timezone.dart' as tz;
+
+class ReceivedNotification {
+ ReceivedNotification({
+ required this.id,
+ required this.title,
+ required this.body,
+ required this.payload,
+ });
+
+ final int id;
+ final String? title;
+ final String? body;
+ final String? payload;
+}
+
+class NotificationService {
+ static int id = 1;
+ static final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
+ FlutterLocalNotificationsPlugin();
+
+ /// Defines a iOS/MacOS notification category for text input actions.
+ static const String darwinNotificationCategoryText = 'textCategory';
+
+ /// Defines a iOS/MacOS notification category for plain actions.
+ static const String darwinNotificationCategoryPlain = 'plainCategory';
+
+ /// A notification action which triggers a url launch event
+ static const String urlLaunchActionId = 'id_1';
+
+ /// A notification action which triggers a App navigation event
+ static const String navigationActionId = 'id_3';
+
+ static String? selectedNotificationPayload;
+
+ /// Streams are created so that app can respond to notification-related events
+ /// since the plugin is initialised in the `main` function
+ static final StreamController
+ didReceiveLocalNotificationStream =
+ StreamController.broadcast();
+
+ static final StreamController selectNotificationStream =
+ StreamController.broadcast();
+
+ static Future initNotification() async {
+ await _configureLocalTimeZone();
+ final NotificationAppLaunchDetails? notificationAppLaunchDetails =
+ !kIsWeb && Platform.isLinux
+ ? null
+ : await flutterLocalNotificationsPlugin
+ .getNotificationAppLaunchDetails();
+ // String initialRoute = HomePage.routeName;
+ if (notificationAppLaunchDetails?.didNotificationLaunchApp ?? false) {
+ selectedNotificationPayload =
+ notificationAppLaunchDetails!.notificationResponse?.payload;
+ // initialRoute = SecondPage.routeName;
+ }
+
+ const AndroidInitializationSettings initializationSettingsAndroid =
+ AndroidInitializationSettings('app_icon');
+
+ final List darwinNotificationCategories =
+ [
+ DarwinNotificationCategory(
+ darwinNotificationCategoryText,
+ actions: [
+ DarwinNotificationAction.text(
+ 'view_scan',
+ 'View scan',
+ buttonTitle: 'View',
+ placeholder: 'Placeholder',
+ ),
+ ],
+ ),
+ ];
+
+ /// Note: permissions aren't requested here just to demonstrate that can be
+ /// done later
+ final DarwinInitializationSettings initializationSettingsDarwin =
+ DarwinInitializationSettings(
+ requestAlertPermission: false,
+ requestBadgePermission: false,
+ requestSoundPermission: false,
+ onDidReceiveLocalNotification:
+ (int id, String? title, String? body, String? payload) async {
+ didReceiveLocalNotificationStream.add(
+ ReceivedNotification(
+ id: id,
+ title: title,
+ body: body,
+ payload: payload,
+ ),
+ );
+ },
+ notificationCategories: darwinNotificationCategories,
+ );
+ final LinuxInitializationSettings initializationSettingsLinux =
+ LinuxInitializationSettings(
+ defaultActionName: 'Open notification',
+ defaultIcon: AssetsLinuxIcon('app_icon.png'),
+ );
+ final InitializationSettings initializationSettings =
+ InitializationSettings(
+ android: initializationSettingsAndroid,
+ iOS: initializationSettingsDarwin,
+ macOS: initializationSettingsDarwin,
+ linux: initializationSettingsLinux,
+ );
+ await flutterLocalNotificationsPlugin.initialize(
+ initializationSettings,
+ onDidReceiveNotificationResponse:
+ (NotificationResponse notificationResponse) {
+ switch (notificationResponse.notificationResponseType) {
+ case NotificationResponseType.selectedNotification:
+ selectNotificationStream.add(notificationResponse.payload);
+ break;
+ case NotificationResponseType.selectedNotificationAction:
+ if (notificationResponse.actionId == navigationActionId) {
+ selectNotificationStream.add(notificationResponse.payload);
+ }
+ break;
+ }
+ },
+ );
+ }
+
+ static Future _configureLocalTimeZone() async {
+ if (kIsWeb || Platform.isLinux) {
+ return;
+ }
+ tz.initializeTimeZones();
+ final String timeZoneName = await FlutterTimezone.getLocalTimezone();
+ tz.setLocalLocation(tz.getLocation(timeZoneName));
+ }
+
+ static Future showNotificationWithActions() async {
+ const AndroidNotificationDetails androidNotificationDetails =
+ AndroidNotificationDetails(
+ 'your channel id',
+ 'your channel name',
+ channelDescription: 'your channel description',
+ importance: Importance.max,
+ priority: Priority.high,
+ ticker: 'ticker',
+ actions: [
+ AndroidNotificationAction(
+ urlLaunchActionId,
+ 'View',
+ ),
+ ],
+ );
+
+ const DarwinNotificationDetails iosNotificationDetails =
+ DarwinNotificationDetails(
+ categoryIdentifier: darwinNotificationCategoryPlain,
+ );
+
+ const DarwinNotificationDetails macOSNotificationDetails =
+ DarwinNotificationDetails(
+ categoryIdentifier: darwinNotificationCategoryPlain,
+ );
+
+ const LinuxNotificationDetails linuxNotificationDetails =
+ LinuxNotificationDetails(
+ actions: [
+ LinuxNotificationAction(
+ key: urlLaunchActionId,
+ label: 'View',
+ ),
+ ],
+ );
+
+ const NotificationDetails notificationDetails = NotificationDetails(
+ android: androidNotificationDetails,
+ iOS: iosNotificationDetails,
+ macOS: macOSNotificationDetails,
+ linux: linuxNotificationDetails,
+ );
+ await flutterLocalNotificationsPlugin.show(
+ id++,
+ 'Scan completed',
+ 'Your devices scan has been completed successfully',
+ notificationDetails,
+ payload: 'item z',
+ );
+ }
+
+ static Future grantPermissions() async {
+ await _isAndroidPermissionGranted();
+ await _requestPermissions();
+ }
+
+ static Future _isAndroidPermissionGranted() async {
+ if (Platform.isAndroid) {
+ return await flutterLocalNotificationsPlugin
+ .resolvePlatformSpecificImplementation<
+ AndroidFlutterLocalNotificationsPlugin>()
+ ?.areNotificationsEnabled() ??
+ false;
+ }
+ return false;
+ }
+
+ static Future _requestPermissions() async {
+ if (Platform.isIOS || Platform.isMacOS) {
+ await flutterLocalNotificationsPlugin
+ .resolvePlatformSpecificImplementation<
+ IOSFlutterLocalNotificationsPlugin>()
+ ?.requestPermissions(
+ alert: true,
+ badge: true,
+ sound: true,
+ );
+ await flutterLocalNotificationsPlugin
+ .resolvePlatformSpecificImplementation<
+ MacOSFlutterLocalNotificationsPlugin>()
+ ?.requestPermissions(
+ alert: true,
+ badge: true,
+ sound: true,
+ );
+ } else if (Platform.isAndroid) {
+ final AndroidFlutterLocalNotificationsPlugin? androidImplementation =
+ flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<
+ AndroidFlutterLocalNotificationsPlugin>();
+
+ return await androidImplementation?.requestNotificationsPermission();
+ }
+ return false;
+ }
+}
diff --git a/lib/services/impls/device_scanner_service.dart b/lib/services/impls/device_scanner_service.dart
index 6d5a80c1..6d797e57 100644
--- a/lib/services/impls/device_scanner_service.dart
+++ b/lib/services/impls/device_scanner_service.dart
@@ -95,4 +95,12 @@ class DeviceScannerService extends ScannerService {
}
return const Stream.empty();
}
+
+ Future getCurrentDevicesCount() async {
+ final scan = await _scanRepository.getOnGoingScan();
+ if (scan != null) {
+ return _deviceRepository.countByScanId(scan.id);
+ }
+ return 0;
+ }
}
diff --git a/lib/values/strings.dart b/lib/values/strings.dart
index bf16cf26..9066a843 100644
--- a/lib/values/strings.dart
+++ b/lib/values/strings.dart
@@ -19,4 +19,5 @@ class StringValue {
static const String customSubnetDesc =
'Scan a custom subnet instead of local one.';
static const String customSubnetHint = 'e.g., 10.102.200.1';
+ static const String hostScanPageTitle = 'Scan for devices';
}
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index f44a2fc2..a23ca65c 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -5,6 +5,8 @@
import FlutterMacOS
import Foundation
+import flutter_local_notifications
+import flutter_timezone
import in_app_review
import isar_flutter_libs
import network_info_plus
@@ -15,6 +17,8 @@ import shared_preferences_foundation
import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
+ FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
+ FlutterTimezonePlugin.register(with: registry.registrar(forPlugin: "FlutterTimezonePlugin"))
InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin"))
IsarFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "IsarFlutterLibsPlugin"))
NetworkInfoPlusPlugin.register(with: registry.registrar(forPlugin: "NetworkInfoPlusPlugin"))
diff --git a/macos/Podfile.lock b/macos/Podfile.lock
index 45b58840..8ba80377 100644
--- a/macos/Podfile.lock
+++ b/macos/Podfile.lock
@@ -1,4 +1,8 @@
PODS:
+ - flutter_local_notifications (0.0.1):
+ - FlutterMacOS
+ - flutter_timezone (0.1.0):
+ - FlutterMacOS
- FlutterMacOS (1.0.0)
- in_app_review (0.2.0):
- FlutterMacOS
@@ -20,6 +24,8 @@ PODS:
- FlutterMacOS
DEPENDENCIES:
+ - flutter_local_notifications (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos`)
+ - flutter_timezone (from `Flutter/ephemeral/.symlinks/plugins/flutter_timezone/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`)
- isar_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/isar_flutter_libs/macos`)
@@ -31,6 +37,10 @@ DEPENDENCIES:
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
EXTERNAL SOURCES:
+ flutter_local_notifications:
+ :path: Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos
+ flutter_timezone:
+ :path: Flutter/ephemeral/.symlinks/plugins/flutter_timezone/macos
FlutterMacOS:
:path: Flutter/ephemeral
in_app_review:
@@ -51,6 +61,8 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
SPEC CHECKSUMS:
+ flutter_local_notifications: 3805ca215b2fb7f397d78b66db91f6a747af52e4
+ flutter_timezone: 6b906d1740654acb16e50b639835628fea851037
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
in_app_review: a850789fad746e89bce03d4aeee8078b45a53fd0
isar_flutter_libs: 43385c99864c168fadba7c9adeddc5d38838ca6a
diff --git a/pubspec.lock b/pubspec.lock
new file mode 100644
index 00000000..56636202
--- /dev/null
+++ b/pubspec.lock
@@ -0,0 +1,1331 @@
+# Generated by pub
+# See https://dart.dev/tools/pub/glossary#lockfile
+packages:
+ _fe_analyzer_shared:
+ dependency: transitive
+ description:
+ name: _fe_analyzer_shared
+ sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a
+ url: "https://pub.dev"
+ source: hosted
+ version: "61.0.0"
+ analyzer:
+ dependency: transitive
+ description:
+ name: analyzer
+ sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.13.0"
+ ansicolor:
+ dependency: transitive
+ description:
+ name: ansicolor
+ sha256: "50e982d500bc863e1d703448afdbf9e5a72eb48840a4f766fa361ffd6877055f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.3"
+ archive:
+ dependency: transitive
+ description:
+ name: archive
+ sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.6.1"
+ args:
+ dependency: transitive
+ description:
+ name: args
+ sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.5.0"
+ async:
+ dependency: transitive
+ description:
+ name: async
+ sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.11.0"
+ auto_size_text:
+ dependency: "direct main"
+ description:
+ name: auto_size_text
+ sha256: "3f5261cd3fb5f2a9ab4e2fc3fba84fd9fcaac8821f20a1d4e71f557521b22599"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.0"
+ bloc:
+ dependency: "direct main"
+ description:
+ name: bloc
+ sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "8.1.4"
+ boolean_selector:
+ dependency: transitive
+ description:
+ name: boolean_selector
+ sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.1"
+ build:
+ dependency: transitive
+ description:
+ name: build
+ sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.1"
+ build_config:
+ dependency: transitive
+ description:
+ name: build_config
+ sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.1"
+ build_daemon:
+ dependency: transitive
+ description:
+ name: build_daemon
+ sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.0.2"
+ build_resolvers:
+ dependency: transitive
+ description:
+ name: build_resolvers
+ sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.2"
+ build_runner:
+ dependency: "direct dev"
+ description:
+ name: build_runner
+ sha256: dd09dd4e2b078992f42aac7f1a622f01882a8492fef08486b27ddde929c19f04
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.12"
+ build_runner_core:
+ dependency: transitive
+ description:
+ name: build_runner_core
+ sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.3.2"
+ built_collection:
+ dependency: transitive
+ description:
+ name: built_collection
+ sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.1.1"
+ built_value:
+ dependency: transitive
+ description:
+ name: built_value
+ sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb
+ url: "https://pub.dev"
+ source: hosted
+ version: "8.9.2"
+ characters:
+ dependency: transitive
+ description:
+ name: characters
+ sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.0"
+ checked_yaml:
+ dependency: transitive
+ description:
+ name: checked_yaml
+ sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.3"
+ clock:
+ dependency: transitive
+ description:
+ name: clock
+ sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.1"
+ code_builder:
+ dependency: transitive
+ description:
+ name: code_builder
+ sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.10.0"
+ collection:
+ dependency: transitive
+ description:
+ name: collection
+ sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.18.0"
+ convert:
+ dependency: transitive
+ description:
+ name: convert
+ sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.1"
+ crypto:
+ dependency: transitive
+ description:
+ name: crypto
+ sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.5"
+ csslib:
+ dependency: transitive
+ description:
+ name: csslib
+ sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.0"
+ csv:
+ dependency: transitive
+ description:
+ name: csv
+ sha256: c6aa2679b2a18cb57652920f674488d89712efaf4d3fdf2e537215b35fc19d6c
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.0.0"
+ cupertino_icons:
+ dependency: "direct main"
+ description:
+ name: cupertino_icons
+ sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.8"
+ dart_ping:
+ dependency: "direct main"
+ description:
+ name: dart_ping
+ sha256: "2f5418d0a5c64e53486caaac78677b25725b1e13c33c5be834ce874ea18bd24f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "9.0.1"
+ dart_ping_ios:
+ dependency: transitive
+ description:
+ name: dart_ping_ios
+ sha256: "17df1b369331ec6c30a91a51db64ac8feed47fad71e444208de06edf2a22415f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.0.2"
+ dart_style:
+ dependency: transitive
+ description:
+ name: dart_style
+ sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.2"
+ dartx:
+ dependency: transitive
+ description:
+ name: dartx
+ sha256: "8b25435617027257d43e6508b5fe061012880ddfdaa75a71d607c3de2a13d244"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.0"
+ dbus:
+ dependency: transitive
+ description:
+ name: dbus
+ sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.7.10"
+ external_app_launcher:
+ dependency: "direct main"
+ description:
+ name: external_app_launcher
+ sha256: fb55cddd706c62ede11056750d5e018ef379820e09739e967873211dd537d833
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.0"
+ fake_async:
+ dependency: transitive
+ description:
+ name: fake_async
+ sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.1"
+ fake_http_client:
+ dependency: transitive
+ description:
+ name: fake_http_client
+ sha256: "4d9be8662a5424f04b95f616f5af9d8041744ad018e5c93f6583e6cf2d3f502d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.0"
+ ffi:
+ dependency: transitive
+ description:
+ name: ffi
+ sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.3"
+ file:
+ dependency: transitive
+ description:
+ name: file
+ sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.0.0"
+ fixnum:
+ dependency: transitive
+ description:
+ name: fixnum
+ sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.0"
+ flutter:
+ dependency: "direct main"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_bloc:
+ dependency: "direct main"
+ description:
+ name: flutter_bloc
+ sha256: b594505eac31a0518bdcb4b5b79573b8d9117b193cc80cc12e17d639b10aa27a
+ url: "https://pub.dev"
+ source: hosted
+ version: "8.1.6"
+ flutter_icmp_ping:
+ dependency: transitive
+ description:
+ name: flutter_icmp_ping
+ sha256: de9633cf65a8c733fae29d08a35d3d4b343620cd1d13e1bfa88eccf56696d896
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.3"
+ flutter_isolate:
+ dependency: transitive
+ description:
+ name: flutter_isolate
+ sha256: "994ddec596da4ca12ca52154fd59404077584643eb7e3f1008a55fda9fe0b76b"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.4"
+ flutter_local_notifications:
+ dependency: "direct main"
+ description:
+ name: flutter_local_notifications
+ sha256: c500d5d9e7e553f06b61877ca6b9c8b92c570a4c8db371038702e8ce57f8a50f
+ url: "https://pub.dev"
+ source: hosted
+ version: "17.2.2"
+ flutter_local_notifications_linux:
+ dependency: transitive
+ description:
+ name: flutter_local_notifications_linux
+ sha256: c49bd06165cad9beeb79090b18cd1eb0296f4bf4b23b84426e37dd7c027fc3af
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.0.1"
+ flutter_local_notifications_platform_interface:
+ dependency: transitive
+ description:
+ name: flutter_local_notifications_platform_interface
+ sha256: "85f8d07fe708c1bdcf45037f2c0109753b26ae077e9d9e899d55971711a4ea66"
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.2.0"
+ flutter_native_splash:
+ dependency: "direct main"
+ description:
+ name: flutter_native_splash
+ sha256: aa06fec78de2190f3db4319dd60fdc8d12b2626e93ef9828633928c2dcaea840
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.1"
+ flutter_test:
+ dependency: "direct dev"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_timezone:
+ dependency: "direct main"
+ description:
+ name: flutter_timezone
+ sha256: ea53c61c9152f271a5e30624a624184804947b6a733ff2b64186bb2579446892
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.1"
+ flutter_web_plugins:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ freezed:
+ dependency: "direct dev"
+ description:
+ name: freezed
+ sha256: a434911f643466d78462625df76fd9eb13e57348ff43fe1f77bbe909522c67a1
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.5.2"
+ freezed_annotation:
+ dependency: "direct main"
+ description:
+ name: freezed_annotation
+ sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.4"
+ frontend_server_client:
+ dependency: transitive
+ description:
+ name: frontend_server_client
+ sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.0.0"
+ get_it:
+ dependency: "direct main"
+ description:
+ name: get_it
+ sha256: d85128a5dae4ea777324730dc65edd9c9f43155c109d5cc0a69cab74139fbac1
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.7.0"
+ glob:
+ dependency: transitive
+ description:
+ name: glob
+ sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.2"
+ graphs:
+ dependency: transitive
+ description:
+ name: graphs
+ sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.2"
+ html:
+ dependency: transitive
+ description:
+ name: html
+ sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.15.4"
+ http:
+ dependency: "direct main"
+ description:
+ name: http
+ sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.2"
+ http_multi_server:
+ dependency: transitive
+ description:
+ name: http_multi_server
+ sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.2.1"
+ http_parser:
+ dependency: transitive
+ description:
+ name: http_parser
+ sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.0.2"
+ image:
+ dependency: transitive
+ description:
+ name: image
+ sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.2.0"
+ in_app_review:
+ dependency: "direct main"
+ description:
+ name: in_app_review
+ sha256: "99869244d09adc76af16bf8fd731dd13cef58ecafd5917847589c49f378cbb30"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.9"
+ in_app_review_platform_interface:
+ dependency: transitive
+ description:
+ name: in_app_review_platform_interface
+ sha256: fed2c755f2125caa9ae10495a3c163aa7fab5af3585a9c62ef4a6920c5b45f10
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.5"
+ injectable:
+ dependency: "direct main"
+ description:
+ name: injectable
+ sha256: "69874ba3ec10e3a0de3f519a184442878291d928f3299d718813f24642585198"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.4"
+ injectable_generator:
+ dependency: "direct dev"
+ description:
+ name: injectable_generator
+ sha256: "7fb573114f8bbdd169f7ae9b0bcd13f464e8170454c27be816d5a1bb39ac8086"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.2"
+ intl:
+ dependency: transitive
+ description:
+ name: intl
+ sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.18.1"
+ io:
+ dependency: transitive
+ description:
+ name: io
+ sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.4"
+ isar:
+ dependency: "direct main"
+ description:
+ name: isar
+ sha256: "99165dadb2cf2329d3140198363a7e7bff9bbd441871898a87e26914d25cf1ea"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.0+1"
+ isar_flutter_libs:
+ dependency: "direct main"
+ description:
+ name: isar_flutter_libs
+ sha256: bc6768cc4b9c61aabff77152e7f33b4b17d2fc93134f7af1c3dd51500fe8d5e8
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.0+1"
+ isar_generator:
+ dependency: "direct dev"
+ description:
+ name: isar_generator
+ sha256: "76c121e1295a30423604f2f819bc255bc79f852f3bc8743a24017df6068ad133"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.0+1"
+ isolate_contactor:
+ dependency: "direct main"
+ description:
+ name: isolate_contactor
+ sha256: e6afce524574cd16a4370dfae75a1718e561ea24175e0b2db5db4ba82d86662f
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.0"
+ js:
+ dependency: transitive
+ description:
+ name: js
+ sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.6.7"
+ json_annotation:
+ dependency: "direct main"
+ description:
+ name: json_annotation
+ sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.9.0"
+ json_serializable:
+ dependency: "direct dev"
+ description:
+ name: json_serializable
+ sha256: ea1432d167339ea9b5bb153f0571d0039607a873d6e04e0117af043f14a1fd4b
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.8.0"
+ leak_tracker:
+ dependency: transitive
+ description:
+ name: leak_tracker
+ sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
+ url: "https://pub.dev"
+ source: hosted
+ version: "10.0.5"
+ leak_tracker_flutter_testing:
+ dependency: transitive
+ description:
+ name: leak_tracker_flutter_testing
+ sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.5"
+ leak_tracker_testing:
+ dependency: transitive
+ description:
+ name: leak_tracker_testing
+ sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.1"
+ lint:
+ dependency: "direct dev"
+ description:
+ name: lint
+ sha256: d758a5211fce7fd3f5e316f804daefecdc34c7e53559716125e6da7388ae8565
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.0"
+ logging:
+ dependency: transitive
+ description:
+ name: logging
+ sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.0"
+ matcher:
+ dependency: transitive
+ description:
+ name: matcher
+ sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.12.16+1"
+ material_color_utilities:
+ dependency: transitive
+ description:
+ name: material_color_utilities
+ sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.11.1"
+ meta:
+ dependency: transitive
+ description:
+ name: meta
+ sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.15.0"
+ mime:
+ dependency: transitive
+ description:
+ name: mime
+ sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.5"
+ multicast_dns:
+ dependency: transitive
+ description:
+ name: multicast_dns
+ sha256: "982c4cc4cda5f98dd477bddfd623e8e4bd1014e7dbf9e7b05052e14a5b550b99"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.3.2+7"
+ nested:
+ dependency: transitive
+ description:
+ name: nested
+ sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.0"
+ network_info_plus:
+ dependency: "direct main"
+ description:
+ name: network_info_plus
+ sha256: "4601b815b1c6a46d84839f65cd774a7d999738471d910fae00d813e9e98b04e1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.1.0+1"
+ network_info_plus_platform_interface:
+ dependency: transitive
+ description:
+ name: network_info_plus_platform_interface
+ sha256: "881f5029c5edaf19c616c201d3d8b366c5b1384afd5c1da5a49e4345de82fb8b"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.3"
+ network_tools:
+ dependency: transitive
+ description:
+ name: network_tools
+ sha256: cf5726a3c3edd82de5f6d6511cb618259a083225ccc2bdb8a55d87b37014cadf
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.0.2"
+ network_tools_flutter:
+ dependency: "direct main"
+ description:
+ path: "."
+ ref: dev
+ resolved-ref: ca55c2955eb9b4ca47757b5f95e2d7237daa4cab
+ url: "https://github.com/osociety/network_tools_flutter.git"
+ source: git
+ version: "2.0.2"
+ nm:
+ dependency: transitive
+ description:
+ name: nm
+ sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.5.0"
+ nsd:
+ dependency: transitive
+ description:
+ name: nsd
+ sha256: "88a3ba4e6dc38363f1256b4b482abdeec396d99df31a064d545e559cb4cb6ba9"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.1"
+ nsd_android:
+ dependency: transitive
+ description:
+ name: nsd_android
+ sha256: "7a38d0b2d21f1e578cd3020940b95b22d5260413dc0c8cf30a987a4e410b166d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.2"
+ nsd_ios:
+ dependency: transitive
+ description:
+ name: nsd_ios
+ sha256: "7034134dd89595362d5e464030081b0d542120a558ab7fe6227df44365df3e8a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.3"
+ nsd_macos:
+ dependency: transitive
+ description:
+ name: nsd_macos
+ sha256: "2403b8d599f50fc9179db1420a0ffc25bfa8bbeb814aa31ca0a71f804fc938da"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.3"
+ nsd_platform_interface:
+ dependency: transitive
+ description:
+ name: nsd_platform_interface
+ sha256: "2f4033fa13cc45375253bf348abdb9712004e656462205543ec9506b43c67bb2"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.6.0"
+ nsd_windows:
+ dependency: transitive
+ description:
+ name: nsd_windows
+ sha256: "06601efdd3268cbce4b90f8e23ae1dab445c97c661fba417821ce118add722e7"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.1"
+ package_config:
+ dependency: transitive
+ description:
+ name: package_config
+ sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.0"
+ package_info_plus:
+ dependency: "direct main"
+ description:
+ name: package_info_plus
+ sha256: "7e76fad405b3e4016cd39d08f455a4eb5199723cf594cd1b8916d47140d93017"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.2.0"
+ package_info_plus_platform_interface:
+ dependency: transitive
+ description:
+ name: package_info_plus_platform_interface
+ sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.1"
+ path:
+ dependency: transitive
+ description:
+ name: path
+ sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.9.0"
+ path_provider:
+ dependency: "direct main"
+ description:
+ name: path_provider
+ sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.4"
+ path_provider_android:
+ dependency: transitive
+ description:
+ name: path_provider_android
+ sha256: "6f01f8e37ec30b07bc424b4deabac37cacb1bc7e2e515ad74486039918a37eb7"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.10"
+ path_provider_foundation:
+ dependency: transitive
+ description:
+ name: path_provider_foundation
+ sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.0"
+ path_provider_linux:
+ dependency: transitive
+ description:
+ name: path_provider_linux
+ sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.1"
+ path_provider_platform_interface:
+ dependency: transitive
+ description:
+ name: path_provider_platform_interface
+ sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.2"
+ path_provider_windows:
+ dependency: transitive
+ description:
+ name: path_provider_windows
+ sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.0"
+ percent_indicator:
+ dependency: "direct main"
+ description:
+ name: percent_indicator
+ sha256: c37099ad833a883c9d71782321cb65c3a848c21b6939b6185f0ff6640d05814c
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.2.3"
+ permission_handler:
+ dependency: "direct main"
+ description:
+ name: permission_handler
+ sha256: "18bf33f7fefbd812f37e72091a15575e72d5318854877e0e4035a24ac1113ecb"
+ url: "https://pub.dev"
+ source: hosted
+ version: "11.3.1"
+ permission_handler_android:
+ dependency: transitive
+ description:
+ name: permission_handler_android
+ sha256: "76e4ab092c1b240d31177bb64d2b0bea43f43d0e23541ec866151b9f7b2490fa"
+ url: "https://pub.dev"
+ source: hosted
+ version: "12.0.12"
+ permission_handler_apple:
+ dependency: transitive
+ description:
+ name: permission_handler_apple
+ sha256: e6f6d73b12438ef13e648c4ae56bd106ec60d17e90a59c4545db6781229082a0
+ url: "https://pub.dev"
+ source: hosted
+ version: "9.4.5"
+ permission_handler_html:
+ dependency: transitive
+ description:
+ name: permission_handler_html
+ sha256: af26edbbb1f2674af65a8f4b56e1a6f526156bc273d0e65dd8075fab51c78851
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.1.3+2"
+ permission_handler_platform_interface:
+ dependency: transitive
+ description:
+ name: permission_handler_platform_interface
+ sha256: fe0ffe274d665be8e34f9c59705441a7d248edebbe5d9e3ec2665f88b79358ea
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.2.2"
+ permission_handler_windows:
+ dependency: transitive
+ description:
+ name: permission_handler_windows
+ sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.2.1"
+ petitparser:
+ dependency: transitive
+ description:
+ name: petitparser
+ sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.0.2"
+ platform:
+ dependency: transitive
+ description:
+ name: platform
+ sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.5"
+ plugin_platform_interface:
+ dependency: transitive
+ description:
+ name: plugin_platform_interface
+ sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.8"
+ pool:
+ dependency: transitive
+ description:
+ name: pool
+ sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.5.1"
+ process_run:
+ dependency: transitive
+ description:
+ name: process_run
+ sha256: "8d9c6198b98fbbfb511edd42e7364e24d85c163e47398919871b952dc86a423e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.14.2"
+ provider:
+ dependency: "direct main"
+ description:
+ name: provider
+ sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.1.2"
+ pub_semver:
+ dependency: transitive
+ description:
+ name: pub_semver
+ sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.4"
+ pubspec_parse:
+ dependency: transitive
+ description:
+ name: pubspec_parse
+ sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.0"
+ recase:
+ dependency: transitive
+ description:
+ name: recase
+ sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.1.0"
+ sembast:
+ dependency: transitive
+ description:
+ name: sembast
+ sha256: "481e0a4199015e0050ee4b42d59d51731b1fb324a1eea5c24557fa72335790b0"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.7.3+2"
+ shared_preferences:
+ dependency: "direct main"
+ description:
+ name: shared_preferences
+ sha256: "746e5369a43170c25816cc472ee016d3a66bc13fcf430c0bc41ad7b4b2922051"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.2"
+ shared_preferences_android:
+ dependency: transitive
+ description:
+ name: shared_preferences_android
+ sha256: a7e8467e9181cef109f601e3f65765685786c1a738a83d7fbbde377589c0d974
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.1"
+ shared_preferences_foundation:
+ dependency: transitive
+ description:
+ name: shared_preferences_foundation
+ sha256: c4b35f6cb8f63c147312c054ce7c2254c8066745125264f0c88739c417fc9d9f
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.5.2"
+ shared_preferences_linux:
+ dependency: transitive
+ description:
+ name: shared_preferences_linux
+ sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.1"
+ shared_preferences_platform_interface:
+ dependency: transitive
+ description:
+ name: shared_preferences_platform_interface
+ sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.1"
+ shared_preferences_web:
+ dependency: transitive
+ description:
+ name: shared_preferences_web
+ sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.2"
+ shared_preferences_windows:
+ dependency: transitive
+ description:
+ name: shared_preferences_windows
+ sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.1"
+ shelf:
+ dependency: transitive
+ description:
+ name: shelf
+ sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.4.1"
+ shelf_web_socket:
+ dependency: transitive
+ description:
+ name: shelf_web_socket
+ sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.0"
+ sky_engine:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.99"
+ source_gen:
+ dependency: transitive
+ description:
+ name: source_gen
+ sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.5.0"
+ source_helper:
+ dependency: transitive
+ description:
+ name: source_helper
+ sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.4"
+ source_span:
+ dependency: transitive
+ description:
+ name: source_span
+ sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.10.0"
+ stack_trace:
+ dependency: transitive
+ description:
+ name: stack_trace
+ sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.11.1"
+ stream_channel:
+ dependency: transitive
+ description:
+ name: stream_channel
+ sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.2"
+ stream_transform:
+ dependency: transitive
+ description:
+ name: stream_transform
+ sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.0"
+ string_scanner:
+ dependency: transitive
+ description:
+ name: string_scanner
+ sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.0"
+ synchronized:
+ dependency: transitive
+ description:
+ name: synchronized
+ sha256: a824e842b8a054f91a728b783c177c1e4731f6b124f9192468457a8913371255
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.2.0"
+ term_glyph:
+ dependency: transitive
+ description:
+ name: term_glyph
+ sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.1"
+ test_api:
+ dependency: transitive
+ description:
+ name: test_api
+ sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.7.2"
+ time:
+ dependency: transitive
+ description:
+ name: time
+ sha256: ad8e018a6c9db36cb917a031853a1aae49467a93e0d464683e029537d848c221
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.4"
+ timezone:
+ dependency: "direct main"
+ description:
+ name: timezone
+ sha256: "2236ec079a174ce07434e89fcd3fcda430025eb7692244139a9cf54fdcf1fc7d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.9.4"
+ timing:
+ dependency: transitive
+ description:
+ name: timing
+ sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.1"
+ typed_data:
+ dependency: transitive
+ description:
+ name: typed_data
+ sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.2"
+ universal_io:
+ dependency: transitive
+ description:
+ name: universal_io
+ sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.2"
+ url_launcher:
+ dependency: "direct main"
+ description:
+ name: url_launcher
+ sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3"
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.3.0"
+ url_launcher_android:
+ dependency: transitive
+ description:
+ name: url_launcher_android
+ sha256: e35a698ac302dd68e41f73250bd9517fe3ab5fa4f18fe4647a0872db61bacbab
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.3.10"
+ url_launcher_ios:
+ dependency: transitive
+ description:
+ name: url_launcher_ios
+ sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.3.1"
+ url_launcher_linux:
+ dependency: transitive
+ description:
+ name: url_launcher_linux
+ sha256: e2b9622b4007f97f504cd64c0128309dfb978ae66adbe944125ed9e1750f06af
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.2.0"
+ url_launcher_macos:
+ dependency: transitive
+ description:
+ name: url_launcher_macos
+ sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.2.0"
+ url_launcher_platform_interface:
+ dependency: transitive
+ description:
+ name: url_launcher_platform_interface
+ sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.2"
+ url_launcher_web:
+ dependency: transitive
+ description:
+ name: url_launcher_web
+ sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.3"
+ url_launcher_windows:
+ dependency: transitive
+ description:
+ name: url_launcher_windows
+ sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.2"
+ uuid:
+ dependency: transitive
+ description:
+ name: uuid
+ sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.7"
+ vector_math:
+ dependency: transitive
+ description:
+ name: vector_math
+ sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.4"
+ vm_service:
+ dependency: transitive
+ description:
+ name: vm_service
+ sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "14.2.5"
+ watcher:
+ dependency: transitive
+ description:
+ name: watcher
+ sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.0"
+ web:
+ dependency: transitive
+ description:
+ name: web
+ sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.0"
+ web_socket:
+ dependency: transitive
+ description:
+ name: web_socket
+ sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.1.6"
+ web_socket_channel:
+ dependency: transitive
+ description:
+ name: web_socket_channel
+ sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.1"
+ win32:
+ dependency: transitive
+ description:
+ name: win32
+ sha256: "68d1e89a91ed61ad9c370f9f8b6effed9ae5e0ede22a270bdfa6daf79fc2290a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.5.4"
+ xdg_directories:
+ dependency: transitive
+ description:
+ name: xdg_directories
+ sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.4"
+ xml:
+ dependency: transitive
+ description:
+ name: xml
+ sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.5.0"
+ xxh3:
+ dependency: transitive
+ description:
+ name: xxh3
+ sha256: a92b30944a9aeb4e3d4f3c3d4ddb3c7816ca73475cd603682c4f8149690f56d7
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.1"
+ yaml:
+ dependency: transitive
+ description:
+ name: yaml
+ sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.2"
+sdks:
+ dart: ">=3.5.0 <4.0.0"
+ flutter: ">=3.24.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index bcb4dad8..39df1dc1 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,7 +3,7 @@ description: A Network Analyzer
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
-version: 1.0.8+26
+version: 1.0.9+27
environment:
sdk: ">=2.17.0 <3.0.0"
@@ -24,8 +24,12 @@ dependencies:
sdk: flutter
# Bloc for state management, replace StatefulWidget
flutter_bloc: ^8.1.1
+ # A cross platform plugin for displaying local notifications.
+ flutter_local_notifications: ^17.2.2
# Native splash screen plugin
flutter_native_splash: ^2.4.0
+ # A flutter plugin for getting the local timezone of the OS.
+ flutter_timezone: ^3.0.0
# Annotations for freezed
freezed_annotation: ^2.4.1
# Service locator
@@ -46,7 +50,11 @@ dependencies:
json_annotation: ^4.8.1
network_info_plus: ^4.0.2
# Helps you discover open ports, devices on subnet and more.
- network_tools_flutter: ^2.0.0
+ # network_tools_flutter: ^2.0.0
+ network_tools_flutter:
+ git:
+ url: https://github.com/osociety/network_tools_flutter.git
+ ref: dev # branch name
# Querying information about the application package, such as CFBundleVersion
package_info_plus: ^4.1.0
path_provider: ^2.1.1
@@ -58,6 +66,8 @@ dependencies:
provider: ^6.0.4
# Reading and writing simple key-value pairs
shared_preferences: ^2.0.15
+ # Time zone database and time zone aware DateTime.
+ timezone: ^0.9.4
# Plugin for launching a URL
url_launcher: ^6.1.6
diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc
index 8af0cec7..07885a4c 100644
--- a/windows/flutter/generated_plugin_registrant.cc
+++ b/windows/flutter/generated_plugin_registrant.cc
@@ -6,12 +6,15 @@
#include "generated_plugin_registrant.h"
+#include
#include
#include
#include
#include
void RegisterPlugins(flutter::PluginRegistry* registry) {
+ FlutterTimezonePluginCApiRegisterWithRegistrar(
+ registry->GetRegistrarForPlugin("FlutterTimezonePluginCApi"));
IsarFlutterLibsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("IsarFlutterLibsPlugin"));
NsdWindowsPluginCApiRegisterWithRegistrar(
diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake
index e69cb1ae..974bb5ed 100644
--- a/windows/flutter/generated_plugins.cmake
+++ b/windows/flutter/generated_plugins.cmake
@@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
+ flutter_timezone
isar_flutter_libs
nsd_windows
permission_handler_windows