Let's start
All checks were successful
continuous-integration/drone Build is passing

This commit is contained in:
supercodeur 2025-05-24 20:12:35 +02:00
commit 6f597ae889
39 changed files with 2034 additions and 0 deletions

171
.drone.yml Normal file
View File

@ -0,0 +1,171 @@
kind: pipeline
type: docker
name: deploy-static-site
steps:
- name: deploy public_html
image: alpine:3.20
volumes:
- name: ididit
path: /var/www/ididit
commands:
- |
if [ -d public_html ] && [ "$(ls -A public_html)" ]; then
target="/var/www/ididit/${DRONE_REPO_OWNER}/${DRONE_REPO_NAME}"
echo "Déploiement vers $target"
rm -rf "$target"
mkdir -p "$target"
cp -r public_html/* "$target/"
echo "Déploiement terminé."
ls -alh "$target"
else
echo "Aucun dossier public_html à déployer."
fi
when:
branch:
- main
event:
- push
- name: build-linux
image: ghcr.io/cirruslabs/flutter:latest
volumes:
- name: ididit
path: /var/www/ididit
commands:
- apt-get update && apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev libstdc++-12-dev tar
- VERSION=$(grep '^version:' pubspec.yaml | awk '{print $2}')
- |
if [ -d linux ]; then
echo "Build Linux..."
flutter pub get
flutter build linux --release
TARGET="/var/www/ididit/$DRONE_REPO_OWNER/$DRONE_REPO_NAME/releases/$VERSION/linux"
mkdir -p "$TARGET"
tar czf "$TARGET/linux-$VERSION.tgz" -C build/linux/x64/release/bundle .
echo "Linux bundle published as $TARGET/linux-$VERSION.tgz"
else
echo "No linux/ directory, skipping."
fi
- name: build-android
image: ghcr.io/cirruslabs/flutter:latest
volumes:
- name: ididit
path: /var/www/ididit
environment:
ANDROID_HOME: /opt/android-sdk
commands:
- VERSION=$(grep '^version:' pubspec.yaml | awk '{print $2}')
- |
if [ -d android ]; then
echo "Build Android..."
flutter pub get
flutter build apk --release
TARGET="/var/www/ididit/$DRONE_REPO_OWNER/$DRONE_REPO_NAME/releases/$VERSION/android"
mkdir -p "$TARGET"
cp build/app/outputs/flutter-apk/app-release.apk "$TARGET/$DRONE_REPO_NAME-$VERSION.apk"
echo "Android build published to $TARGET"
else
echo "No android/ directory, skipping."
fi
- name: build-web
image: ghcr.io/cirruslabs/flutter:latest
volumes:
- name: ididit
path: /var/www/ididit
commands:
- apt-get update && apt-get install -y tar
- VERSION=$(grep '^version:' pubspec.yaml | awk '{print $2}')
- |
if [ -d web ]; then
echo "Build Web..."
flutter pub get
flutter build web --release
TARGET="/var/www/ididit/$DRONE_REPO_OWNER/$DRONE_REPO_NAME/releases/$VERSION/web"
mkdir -p "$TARGET"
tar czf "$TARGET/web-$VERSION.tgz" -C build/web .
echo "Web bundle published as $TARGET/web-$VERSION.tgz"
else
echo "No web/ directory, skipping."
fi
- name: generate-versions-html
image: alpine:3.20
volumes:
- name: ididit
path: /var/www/ididit
commands:
- OWNER="$DRONE_REPO_OWNER"
- REPO="$DRONE_REPO_NAME"
- RELEASES_DIR="/var/www/ididit/$OWNER/$REPO/releases"
- REPO_URL="https://gitea.bymycode.com/$OWNER/$REPO"
- |
HTML="$RELEASES_DIR/index.html"
echo '<!DOCTYPE html>' > "$HTML"
echo '<html lang="fr">' >> "$HTML"
echo '<head>' >> "$HTML"
echo ' <meta charset="UTF-8">' >> "$HTML"
echo " <title>Versions disponibles pour $REPO</title>" >> "$HTML"
echo ' <style>' >> "$HTML"
echo ' body { font-family: sans-serif; background: #f7f7f7; color: #222; margin: 2em; }' >> "$HTML"
echo ' h1 { color: #346beb; }' >> "$HTML"
echo ' h2 { margin-top: 2em; }' >> "$HTML"
echo ' ul { list-style: none; padding: 0; }' >> "$HTML"
echo ' li { margin: 0.5em 0; }' >> "$HTML"
echo ' a { color: #346beb; text-decoration: none; font-weight: bold; }' >> "$HTML"
echo ' .repo { margin-top: 2em; font-size: 0.95em; }' >> "$HTML"
echo ' .icon { margin-right: 0.5em; }' >> "$HTML"
echo ' </style>' >> "$HTML"
echo '</head>' >> "$HTML"
echo '<body>' >> "$HTML"
echo " <h1>Versions disponibles pour <span style=\"color:#346beb;\">$REPO</span></h1>" >> "$HTML"
echo " <div class=\"repo\">" >> "$HTML"
echo " 📦 <a href=\"$REPO_URL\">Voir le repository sur gitea.ByMyCode.com</a>" >> "$HTML"
echo " </div>" >> "$HTML"
echo " <hr>" >> "$HTML"
for version_dir in $(ls -1 "$RELEASES_DIR" | sort -Vr); do
if [ -d "$RELEASES_DIR/$version_dir" ]; then
echo "<h2>Version $version_dir</h2>" >> "$HTML"
# Linux bundle
if [ -f "$RELEASES_DIR/$version_dir/linux/linux-$version_dir.tgz" ]; then
echo "<ul><li><strong>Linux :</strong></li>" >> "$HTML"
echo "<li><span class='icon'>🐧</span><a href=\"./$version_dir/linux/linux-$version_dir.tgz\">linux-$version_dir.tgz</a></li>" >> "$HTML"
echo "</ul>" >> "$HTML"
fi
# Android
if [ -d "$RELEASES_DIR/$version_dir/android" ]; then
for f in "$RELEASES_DIR/$version_dir/android/"*; do
fname=$(basename "$f")
echo "<ul><li><strong>Android :</strong></li>" >> "$HTML"
echo "<li><span class='icon'>🤖</span><a href=\"./$version_dir/android/$fname\">$fname</a></li>" >> "$HTML"
echo "</ul>" >> "$HTML"
done
fi
# Web bundle
if [ -f "$RELEASES_DIR/$version_dir/web/web-$version_dir.tgz" ]; then
echo "<ul><li><strong>Web :</strong></li>" >> "$HTML"
echo "<li><span class='icon'>🌍</span><a href=\"./$version_dir/web/web-$version_dir.tgz\">web-$version_dir.tgz</a></li>" >> "$HTML"
echo "</ul>" >> "$HTML"
fi
echo "<hr>" >> "$HTML"
fi
done
echo "<footer style='margin-top:2em;font-size:0.9em;color:#888;'>Généré automatiquement par ByMyCode.com CI 🚀</footer>" >> "$HTML"
echo "</body>" >> "$HTML"
echo "</html>" >> "$HTML"
echo "Fichier versions.html généré dans $HTML"
- name: list-published
image: alpine:3.20
volumes:
- name: ididit
path: /var/www/ididit
commands:
- ls -alR /var/www/ididit/$DRONE_REPO_OWNER/$DRONE_REPO_NAME/releases || echo "No releases published."
volumes:
- name: ididit
host:
path: /var/www/ididit

45
.gitignore vendored Normal file
View File

@ -0,0 +1,45 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release

45
.metadata Normal file
View File

@ -0,0 +1,45 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "ea121f8859e4b13e47a8f845e4586164519588bc"
channel: "stable"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
- platform: android
create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
- platform: ios
create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
- platform: linux
create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
- platform: macos
create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
- platform: web
create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
- platform: windows
create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'

9
README.md Normal file
View File

@ -0,0 +1,9 @@
# monitor2
Because the first one were fucked up.
Monitors URLs you need.
## Getting Started
All you need is flutter. Enjoy.

28
analysis_options.yaml Normal file
View File

@ -0,0 +1,28 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at https://dart.dev/lints.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options

14
android/.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
.cxx/
# Remember to never publicly share your keystore.
# See https://flutter.dev/to/reference-keystore
key.properties
**/*.keystore
**/*.jks

View File

@ -0,0 +1,44 @@
plugins {
id("com.android.application")
id("kotlin-android")
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id("dev.flutter.flutter-gradle-plugin")
}
android {
namespace = "com.bymycode.supercodeur.monitor2"
compileSdk = flutter.compileSdkVersion
ndkVersion = "27.0.12077973"
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.bymycode.supercodeur.monitor2"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.getByName("debug")
}
}
}
flutter {
source = "../.."
}

View File

@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@ -0,0 +1,48 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<application
android:label="monitor2"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>

View File

@ -0,0 +1,5 @@
package com.bymycode.supercodeur.monitor2
import io.flutter.embedding.android.FlutterActivity
class MainActivity : FlutterActivity()

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

21
android/build.gradle.kts Normal file
View File

@ -0,0 +1,21 @@
allprojects {
repositories {
google()
mavenCentral()
}
}
val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get()
rootProject.layout.buildDirectory.value(newBuildDir)
subprojects {
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
project.layout.buildDirectory.value(newSubprojectBuildDir)
}
subprojects {
project.evaluationDependsOn(":app")
}
tasks.register<Delete>("clean") {
delete(rootProject.layout.buildDirectory)
}

View File

@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
android.enableJetifier=true

View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip

View File

@ -0,0 +1,25 @@
pluginManagement {
val flutterSdkPath = run {
val properties = java.util.Properties()
file("local.properties").inputStream().use { properties.load(it) }
val flutterSdkPath = properties.getProperty("flutter.sdk")
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
flutterSdkPath
}
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "8.7.0" apply false
id("org.jetbrains.kotlin.android") version "1.8.22" apply false
}
include(":app")

BIN
assets/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

View File

@ -0,0 +1,34 @@
import 'package:flutter/material.dart';
class AddSiteDialog extends StatefulWidget {
const AddSiteDialog({super.key});
@override
State<AddSiteDialog> createState() => _AddSiteDialogState();
}
class _AddSiteDialogState extends State<AddSiteDialog> {
final controller = TextEditingController();
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text('Ajouter une URL'),
content: TextField(
controller: controller,
decoration: InputDecoration(hintText: 'https://exemple.com'),
autofocus: true,
),
actions: [
TextButton(
child: Text('Annuler'),
onPressed: () => Navigator.pop(context),
),
ElevatedButton(
child: Text('Ajouter'),
onPressed: () => Navigator.pop(context, controller.text.trim()),
),
],
);
}
}

View File

@ -0,0 +1,117 @@
import 'package:flutter/material.dart';
import '../log/screen_logspage.dart';
import '../log/class_sitecheck.dart';
import '../log/class_sitelog.dart';
import 'dialog_addsite.dart';
class HomePage extends StatelessWidget {
final List<SiteCheck> sites;
final List<SiteLog> logs;
final Function(String) addSite;
final Function(int) removeSite;
final VoidCallback forceCheck;
final bool isChecking;
const HomePage({
super.key,
required this.sites,
required this.logs,
required this.addSite,
required this.removeSite,
required this.forceCheck,
required this.isChecking,
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('🌐 Surveillance de sites'),
actions: [
IconButton(
icon: Icon(Icons.list_alt),
tooltip: 'Voir tous les logs',
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => LogsPage(logs: logs)),
);
},
),
IconButton(
icon:
isChecking
? SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(
color: Colors.white,
strokeWidth: 3,
),
)
: Icon(Icons.refresh),
tooltip:
isChecking ? 'Vérification en cours...' : 'Forcer les tests',
onPressed: isChecking ? null : forceCheck,
),
],
),
body: ListView.builder(
itemCount: sites.length,
itemBuilder: (context, index) {
final site = sites[index];
final lastLog = logs.lastWhere(
(l) => l.url == site.url,
orElse: () => SiteLog(DateTime.now(), site.url, 0),
);
final isOk = lastLog.statusCode == 200;
return Card(
child: ListTile(
leading: Text(isOk ? '' : '', style: TextStyle(fontSize: 24)),
title: Text(site.url),
subtitle:
lastLog.statusCode == 0
? Text('Aucune vérification')
: Text(
isOk ? 'OK' : 'Erreur: ${lastLog.statusCode}',
style: TextStyle(
color: isOk ? Colors.black : Colors.red.withAlpha(10),
fontWeight:
isOk ? FontWeight.normal : FontWeight.bold,
),
),
tileColor: isOk ? null : Colors.red.withAlpha(10),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder:
(_) => LogsPage(
logs: logs.where((l) => l.url == site.url).toList(),
),
),
);
},
trailing: IconButton(
icon: Icon(Icons.delete, color: Colors.grey),
onPressed: () => removeSite(index),
),
),
);
},
),
floatingActionButton: FloatingActionButton(
child: Text('', style: TextStyle(fontSize: 24)),
onPressed: () async {
final url = await showDialog<String>(
context: context,
builder: (context) => AddSiteDialog(),
);
if (url != null && url.isNotEmpty) {
addSite(url);
}
},
),
);
}
}

View File

@ -0,0 +1,191 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import '../monitor/monitor2app.dart';
import 'package:url_launcher/url_launcher.dart';
const String securityURL =
"https://ididit.bymycode.com/supercodeur/monitor2/isSoftwareActive_1.0.0.txt";
class KillSwitchHomePage extends StatefulWidget {
const KillSwitchHomePage({super.key});
@override
KillSwitchHomePageState createState() => KillSwitchHomePageState();
}
class KillSwitchHomePageState extends State<KillSwitchHomePage> {
String _message = "Vérification de l'état...";
bool _isLoading = true;
@override
void initState() {
super.initState();
_checkStatus();
}
Future<void> _checkStatus() async {
setState(() {
_isLoading = true;
_message = "Vérification de l'état...";
});
try {
final response = await http.get(Uri.parse(securityURL));
if (!mounted) return;
if (response.statusCode >= 200 && response.statusCode < 300) {
final data = response.body;
if (data.contains('active: true')) {
setState(() {
_isLoading = false;
_message = "Application active, c'est parti...";
});
if (!mounted) return;
await Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => const Monitor2App()),
);
} else {
_updateMessage("L'application est désormais bloquée.");
}
} else if (response.statusCode >= 400 && response.statusCode < 500) {
_updateMessage("Veuillez mettre à jour l'application.");
} else {
_showNetworkError();
}
} catch (e) {
_showNetworkError();
} finally {
if (mounted) {
setState(() {
_isLoading = false;
});
}
}
}
void _showNetworkError() {
setState(() {
_message =
"Une connexion réseau est nécessaire pour accéder à l'application.";
_isLoading = false;
});
Timer(const Duration(seconds: 5), () {
setState(() {
_isLoading = true;
_checkStatus();
});
});
}
void _updateMessage(String message) {
setState(() {
_message = message;
_isLoading = false;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Initialisation')),
body: Center(
child:
_isLoading
? const CircularProgressIndicator()
: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'TourPet',
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
color: Colors.teal,
),
),
Text(_message, textAlign: TextAlign.center),
const SizedBox(height: 20),
Image.asset(
'assets/icon.png',
width: MediaQuery.of(context).size.width * 0.25,
fit: BoxFit.contain,
),
const SizedBox(height: 20),
Text(
'Copyright (c) 2025 SuperCodeur',
style: TextStyle(fontSize: 14, color: Colors.grey[600]),
),
const SizedBox(height: 10),
GestureDetector(
onTap:
() =>
_launchEmail('cgifl300+supercodeur@gmail.com'),
child: const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('✉️ ', style: TextStyle(fontSize: 18)),
Text(
'cgifl300+supercodeur@gmail.com',
style: TextStyle(
color: Colors.blue,
fontSize: 14,
decoration: TextDecoration.underline,
),
),
],
),
),
const SizedBox(height: 10),
GestureDetector(
onTap:
() => _launchUrl(
'https://ididit.bymycode.com/supercodeur/monitor2/',
),
child: const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('🌐 ', style: TextStyle(fontSize: 18)),
Text(
'Visiter le site du projet',
style: TextStyle(
color: Colors.blue,
fontSize: 14,
decoration: TextDecoration.underline,
),
),
],
),
),
],
),
),
),
);
}
Future<void> _launchUrl(String url) async {
final Uri uri = Uri.parse(url);
if (!await launchUrl(uri, mode: LaunchMode.externalApplication)) {
throw Exception('Could not launch $url');
}
}
void _launchEmail(String email) async {
final Uri emailUri = Uri(
scheme: 'mailto',
path: email,
queryParameters: {'subject': 'Hello', 'body': 'Test'},
);
if (await canLaunchUrl(emailUri)) {
await launchUrl(emailUri);
} else {
throw 'Could not launch email client';
}
}
}

View File

@ -0,0 +1,7 @@
class SiteCheck {
final String url;
SiteCheck(this.url);
String toLine() => url;
static SiteCheck fromLine(String line) => SiteCheck(line);
}

View File

@ -0,0 +1,14 @@
class SiteLog {
final DateTime date;
final String url;
final int statusCode;
SiteLog(this.date, this.url, this.statusCode);
String toCsv() => '${date.toIso8601String()},$url,$statusCode';
static SiteLog fromCsv(String line) {
final parts = line.split(',');
return SiteLog(DateTime.parse(parts[0]), parts[1], int.parse(parts[2]));
}
}

View File

@ -0,0 +1,60 @@
import 'package:flutter/material.dart';
import 'package:monitor2/log/class_sitelog.dart';
class LogsPage extends StatefulWidget {
final List<SiteLog> logs;
const LogsPage({super.key, required this.logs});
@override
State<LogsPage> createState() => _LogsPageState();
}
class _LogsPageState extends State<LogsPage> {
String sortBy = 'date';
@override
Widget build(BuildContext context) {
final logs = List.of(widget.logs);
if (sortBy == 'date') {
logs.sort((a, b) => b.date.compareTo(a.date));
} else {
logs.sort((a, b) => a.statusCode.compareTo(b.statusCode));
}
return Scaffold(
appBar: AppBar(
title: Text('📝 Logs'),
actions: [
PopupMenuButton<String>(
onSelected: (value) => setState(() => sortBy = value),
itemBuilder:
(context) => [
PopupMenuItem(value: 'date', child: Text('Trier par date')),
PopupMenuItem(
value: 'status',
child: Text('Trier par statut'),
),
],
),
],
),
body: ListView.builder(
itemCount: logs.length,
itemBuilder: (context, index) {
final log = logs[index];
final isOk = log.statusCode == 200;
return ListTile(
leading: Text(isOk ? '🟢' : '🔴', style: TextStyle(fontSize: 20)),
title: Text(log.url),
subtitle: Text(
'${log.date.toLocal()} - '
'${isOk ? 'OK' : 'Erreur: ${log.statusCode == -1 ? 'Timeout/Network' : log.statusCode}'}',
),
tileColor: isOk ? null : Colors.red.withAlpha(10),
);
},
),
);
}
}

6
lib/main.dart Normal file
View File

@ -0,0 +1,6 @@
import 'package:flutter/material.dart';
import 'monitor/monitor2app.dart';
void main() {
runApp(Monitor2App());
}

View File

@ -0,0 +1,175 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';
import '../homepage/screen_homepage.dart';
import '../log/class_sitecheck.dart';
import '../log/class_sitelog.dart';
class Monitor2App extends StatefulWidget {
const Monitor2App({super.key});
@override
State<Monitor2App> createState() => Monitor2AppState();
}
class Monitor2AppState extends State<Monitor2App> {
List<SiteCheck> sites = [];
List<SiteLog> logs = [];
Timer? timer;
bool isChecking = false;
final GlobalKey<ScaffoldMessengerState> messengerKey =
GlobalKey<ScaffoldMessengerState>();
@override
void initState() {
super.initState();
loadSites().then((_) {
loadLogs().then((_) {
setState(() {});
checkAllSites();
timer = Timer.periodic(
const Duration(hours: 1),
(_) => checkAllSites(),
);
});
});
}
@override
void dispose() {
timer?.cancel();
super.dispose();
}
Future<File> getLogFile() async {
final dir = await getApplicationDocumentsDirectory();
return File('${dir.path}/logs.dat');
}
Future<File> getSitesFile() async {
final dir = await getApplicationDocumentsDirectory();
return File('${dir.path}/sites.dat');
}
Future<void> loadLogs() async {
try {
final file = await getLogFile();
if (await file.exists()) {
final lines = await file.readAsLines();
logs = lines.map((l) => SiteLog.fromCsv(l)).toList();
}
} catch (_) {}
}
Future<void> saveLogs() async {
final file = await getLogFile();
final lastLogs =
logs.length > 10000 ? logs.sublist(logs.length - 10000) : logs;
await file.writeAsString(lastLogs.map((l) => l.toCsv()).join('\n'));
}
Future<void> loadSites() async {
try {
final file = await getSitesFile();
if (await file.exists()) {
final lines = await file.readAsLines();
sites = lines.map((l) => SiteCheck.fromLine(l)).toList();
} else {
sites = [
SiteCheck('https://flutter.dev'),
SiteCheck('https://google.com'),
];
await saveSites();
}
} catch (_) {
sites = [
SiteCheck('https://flutter.dev'),
SiteCheck('https://google.com'),
];
await saveSites();
}
}
Future<void> saveSites() async {
final file = await getSitesFile();
final lastSites =
sites.length > 100 ? sites.sublist(sites.length - 100) : sites;
await file.writeAsString(lastSites.map((s) => s.toLine()).join('\n'));
}
Future<void> checkAllSites({bool showSnackBar = false}) async {
if (isChecking) return;
setState(() {
isChecking = true;
});
for (var site in sites) {
try {
final response = await http
.get(Uri.parse(site.url))
.timeout(const Duration(seconds: 10));
addLog(site.url, response.statusCode);
} catch (e) {
addLog(site.url, -1);
}
}
setState(() {
isChecking = false;
});
if (showSnackBar) {
messengerKey.currentState?.showSnackBar(
const SnackBar(content: Text('Vérification des sites terminée ✅')),
);
}
}
void addLog(String url, int statusCode) {
logs.add(SiteLog(DateTime.now(), url, statusCode));
if (logs.length > 10000) {
logs = logs.sublist(logs.length - 10000);
}
saveLogs();
}
void addSite(String url) async {
if (sites.length >= 100) {
messengerKey.currentState?.showSnackBar(
const SnackBar(content: Text('Limite de 100 sites atteinte 🚫')),
);
return;
}
setState(() {
sites.add(SiteCheck(url));
});
await saveSites();
}
void removeSite(int index) async {
setState(() {
sites.removeAt(index);
});
await saveSites();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
scaffoldMessengerKey: messengerKey,
title: 'Surveillance de sites',
theme: ThemeData(primarySwatch: Colors.blue),
home: HomePage(
sites: sites,
logs: logs,
addSite: addSite,
removeSite: removeSite,
forceCheck: () => checkAllSites(showSnackBar: true),
isChecking: isChecking,
),
);
}
}

147
public_html/index.html Normal file
View File

@ -0,0 +1,147 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>🌐 monitor2 Surveillance d'URL</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
background: linear-gradient(135deg, #e0e7ff 0%, #f1f5f9 100%);
font-family: 'Segoe UI', 'Arial', sans-serif;
color: #22223b;
margin: 0;
padding: 0;
}
header {
background: #4f46e5;
color: #fff;
padding: 2rem 1rem 1rem 1rem;
text-align: center;
border-bottom-left-radius: 2rem;
border-bottom-right-radius: 2rem;
box-shadow: 0 4px 16px rgba(79, 70, 229, 0.15);
}
header h1 {
font-size: 2.5rem;
margin: 0;
letter-spacing: 2px;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5em;
}
header p {
margin: 0.5em 0 0 0;
font-size: 1.2rem;
opacity: 0.95;
}
main {
max-width: 700px;
margin: 2rem auto;
background: #fff;
border-radius: 1.5rem;
box-shadow: 0 2px 12px rgba(79, 70, 229, 0.08);
padding: 2rem 1.5rem;
}
h2 {
color: #4f46e5;
margin-top: 1.5em;
display: flex;
align-items: center;
gap: 0.5em;
font-size: 1.5rem;
}
ul {
margin: 1em 0;
padding-left: 1.5em;
}
li {
margin-bottom: 0.7em;
font-size: 1.08rem;
}
.links {
display: flex;
flex-wrap: wrap;
gap: 1em;
margin: 2em 0 1em 0;
justify-content: center;
}
.links a {
display: inline-block;
background: #4f46e5;
color: #fff;
text-decoration: none;
padding: 0.7em 1.3em;
border-radius: 2em;
font-weight: 600;
font-size: 1.08rem;
transition: background 0.2s, transform 0.2s;
box-shadow: 0 2px 8px rgba(79, 70, 229, 0.07);
}
.links a:hover {
background: #6366f1;
transform: translateY(-2px) scale(1.03);
}
.url-list {
margin-top: 1em;
display: flex;
flex-direction: column;
gap: 0.5em;
}
.url-item {
background: #e0e7ff;
border-radius: 0.7em;
padding: 0.5em 1em;
display: flex;
align-items: center;
gap: 0.7em;
font-size: 1rem;
}
.url-status {
font-size: 1.2em;
font-weight: bold;
}
footer {
text-align: center;
margin: 2em 0 1em 0;
color: #888;
font-size: 0.98em;
opacity: 0.8;
}
@media (max-width: 600px) {
main { padding: 1em 0.5em; }
header h1 { font-size: 2rem; }
h2 { font-size: 1.2rem; }
}
</style>
</head>
<body>
<header>
<h1>🌐 monitor2 <span>🔎</span></h1>
<p>Surveillez la disponibilité de vos URL favorites, simplement et efficacement! 🚦</p>
</header>
<main>
<section>
<h2>✨ À propos du projet</h2>
<ul>
<li>🕒 Vérifie automatiquement la disponibilité de vos URL toutes les heures.</li>
<li>📱 Fonctionne directement sur votre téléphone, sans serveur externe.</li>
<li>📝 Enregistre des <strong>logs</strong> localement pour chaque vérification.</li>
<li>🔒 Respecte votre vie privée: aucune donnée transmise en dehors de votre appareil.</li>
</ul>
</section>
<section>
<h2>🔗 Ressources du projet</h2>
<div class="links">
<a href="https://gitea.bymycode.com/supercodeur/monitor2" target="_blank">💻 Code source</a>
<a href="https://gitea.bymycode.com/supercodeur/monitor2/wiki" target="_blank">📚 Wiki</a>
<a href="https://ididit.bymycode.com/supercodeur/monitor2/releases" target="_blank">⬇️ Builds & Releases</a>
</div>
</section>
</main>
<footer>
Fait avec ❤️ par <strong>SuperCodeur</strong> &nbsp;|&nbsp; Projet open-source 2025
</footer>
</body>
</html>

View File

@ -0,0 +1 @@
active: true

View File

@ -0,0 +1,130 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>monitor2 En construction 🏗️</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
background: linear-gradient(135deg, #f8fafc 0%, #e0e7ff 100%);
font-family: 'Segoe UI', 'Arial', sans-serif;
color: #22223b;
margin: 0;
padding: 0;
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.container {
background: #fff;
border-radius: 1.5em;
box-shadow: 0 4px 16px rgba(79,70,229,0.10);
padding: 2.5em 2em 2em 2em;
text-align: center;
max-width: 400px;
margin: 2em;
}
h1 {
font-size: 2.3em;
color: #4f46e5;
margin-bottom: 0.2em;
display: flex;
align-items: center;
justify-content: center;
gap: 0.4em;
}
.emojis {
font-size: 2.2em;
margin: 0.5em 0 0.7em 0;
letter-spacing: 0.2em;
animation: bounce 2s infinite;
}
@keyframes bounce {
0%, 100% { transform: translateY(0);}
50% { transform: translateY(-10px);}
}
.message {
font-size: 1.18em;
margin: 1.2em 0 0.8em 0;
color: #444;
}
.waiting {
font-size: 1.1em;
color: #6366f1;
margin-bottom: 1.3em;
}
.progress-bar {
background: #e0e7ff;
border-radius: 1em;
overflow: hidden;
width: 80%;
height: 18px;
margin: 1.5em auto 1em auto;
box-shadow: 0 1px 4px #c7d2fe33;
position: relative;
}
.progress {
background: linear-gradient(90deg, #6366f1 0%, #818cf8 100%);
height: 100%;
width: 0%;
transition: width 0.5s;
}
.back-link {
display: inline-block;
margin-top: 1.8em;
padding: 0.7em 1.3em;
background: #4f46e5;
color: #fff;
border-radius: 2em;
text-decoration: none;
font-weight: 600;
transition: background 0.15s, transform 0.15s;
font-size: 1.07em;
}
.back-link:hover {
background: #6366f1;
transform: translateY(-2px) scale(1.04);
}
footer {
margin-top: 2em;
color: #888;
font-size: 0.98em;
opacity: 0.85;
text-align: center;
}
</style>
</head>
<body>
<div class="container">
<h1>monitor2 <span>🏗️</span></h1>
<div class="emojis">🚧⏳🕒</div>
<div class="message">
Ce projet est actuellement <strong>en construction</strong>.<br>
Le téléchargement sera bientôt disponible&nbsp;!
</div>
<div class="waiting">
Merci de votre patience&nbsp;😊<br>
<span style="font-size:1.4em;">Prenez un café&nbsp;☕ ou rafraîchissez la page plus tard&nbsp;!</span>
</div>
<div class="progress-bar">
<div class="progress" id="progress"></div>
</div>
<a class="back-link" href="../">⬅️ Retour à la racine du projet</a>
</div>
<footer>
monitor2 ByMyCode.com<br>
Dernière mise à jour: 2025
</footer>
<script>
// Animation de barre de progression pour passer le temps
let progress = 0;
const bar = document.getElementById('progress');
setInterval(() => {
progress = (progress + Math.random() * 15) % 100;
bar.style.width = progress + "%";
}, 700);
</script>
</body>
</html>

490
pubspec.lock Normal file
View File

@ -0,0 +1,490 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
archive:
dependency: transitive
description:
name: archive
sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd"
url: "https://pub.dev"
source: hosted
version: "4.0.7"
args:
dependency: transitive
description:
name: args
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
url: "https://pub.dev"
source: hosted
version: "2.7.0"
async:
dependency: transitive
description:
name: async
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
url: "https://pub.dev"
source: hosted
version: "2.13.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
characters:
dependency: transitive
description:
name: characters
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
url: "https://pub.dev"
source: hosted
version: "1.4.0"
checked_yaml:
dependency: transitive
description:
name: checked_yaml
sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
url: "https://pub.dev"
source: hosted
version: "2.0.3"
cli_util:
dependency: transitive
description:
name: cli_util
sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c
url: "https://pub.dev"
source: hosted
version: "0.4.2"
clock:
dependency: transitive
description:
name: clock
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
url: "https://pub.dev"
source: hosted
version: "1.1.2"
collection:
dependency: transitive
description:
name: collection
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
url: "https://pub.dev"
source: hosted
version: "1.19.1"
crypto:
dependency: transitive
description:
name: crypto
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
url: "https://pub.dev"
source: hosted
version: "3.0.6"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
url: "https://pub.dev"
source: hosted
version: "1.0.8"
fake_async:
dependency: transitive
description:
name: fake_async
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
url: "https://pub.dev"
source: hosted
version: "1.3.3"
ffi:
dependency: transitive
description:
name: ffi
sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_launcher_icons:
dependency: "direct main"
description:
name: flutter_launcher_icons
sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea"
url: "https://pub.dev"
source: hosted
version: "0.13.1"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
url: "https://pub.dev"
source: hosted
version: "5.0.0"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
http:
dependency: "direct main"
description:
name: http
sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b"
url: "https://pub.dev"
source: hosted
version: "1.4.0"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
url: "https://pub.dev"
source: hosted
version: "4.1.2"
image:
dependency: transitive
description:
name: image
sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928"
url: "https://pub.dev"
source: hosted
version: "4.5.4"
json_annotation:
dependency: transitive
description:
name: json_annotation
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
url: "https://pub.dev"
source: hosted
version: "4.9.0"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
url: "https://pub.dev"
source: hosted
version: "10.0.9"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
url: "https://pub.dev"
source: hosted
version: "3.0.9"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
lints:
dependency: transitive
description:
name: lints
sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
url: "https://pub.dev"
source: hosted
version: "5.1.1"
matcher:
dependency: transitive
description:
name: matcher
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
url: "https://pub.dev"
source: hosted
version: "0.12.17"
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: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
url: "https://pub.dev"
source: hosted
version: "1.16.0"
path:
dependency: transitive
description:
name: path
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
url: "https://pub.dev"
source: hosted
version: "1.9.1"
path_provider:
dependency: "direct main"
description:
name: path_provider
sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
url: "https://pub.dev"
source: hosted
version: "2.1.5"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9
url: "https://pub.dev"
source: hosted
version: "2.2.17"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_foundation
sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
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"
petitparser:
dependency: transitive
description:
name: petitparser
sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646"
url: "https://pub.dev"
source: hosted
version: "6.1.0"
platform:
dependency: transitive
description:
name: platform
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
url: "https://pub.dev"
source: hosted
version: "3.1.6"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
url: "https://pub.dev"
source: hosted
version: "2.1.8"
posix:
dependency: transitive
description:
name: posix
sha256: f0d7856b6ca1887cfa6d1d394056a296ae33489db914e365e2044fdada449e62
url: "https://pub.dev"
source: hosted
version: "6.0.2"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
source_span:
dependency: transitive
description:
name: source_span
sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
url: "https://pub.dev"
source: hosted
version: "1.10.1"
stack_trace:
dependency: transitive
description:
name: stack_trace
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
url: "https://pub.dev"
source: hosted
version: "1.12.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
url: "https://pub.dev"
source: hosted
version: "1.4.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
url: "https://pub.dev"
source: hosted
version: "1.2.2"
test_api:
dependency: transitive
description:
name: test_api
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
url: "https://pub.dev"
source: hosted
version: "0.7.4"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
url: "https://pub.dev"
source: hosted
version: "1.4.0"
url_launcher:
dependency: "direct main"
description:
name: url_launcher
sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603"
url: "https://pub.dev"
source: hosted
version: "6.3.1"
url_launcher_android:
dependency: transitive
description:
name: url_launcher_android
sha256: "8582d7f6fe14d2652b4c45c9b6c14c0b678c2af2d083a11b604caeba51930d79"
url: "https://pub.dev"
source: hosted
version: "6.3.16"
url_launcher_ios:
dependency: transitive
description:
name: url_launcher_ios
sha256: "7f2022359d4c099eea7df3fdf739f7d3d3b9faf3166fb1dd390775176e0b76cb"
url: "https://pub.dev"
source: hosted
version: "6.3.3"
url_launcher_linux:
dependency: transitive
description:
name: url_launcher_linux
sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935"
url: "https://pub.dev"
source: hosted
version: "3.2.1"
url_launcher_macos:
dependency: transitive
description:
name: url_launcher_macos
sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2"
url: "https://pub.dev"
source: hosted
version: "3.2.2"
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: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77"
url: "https://pub.dev"
source: hosted
version: "3.1.4"
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: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
url: "https://pub.dev"
source: hosted
version: "15.0.0"
web:
dependency: transitive
description:
name: web
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
url: "https://pub.dev"
source: hosted
version: "1.1.1"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
xml:
dependency: transitive
description:
name: xml
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
url: "https://pub.dev"
source: hosted
version: "6.5.0"
yaml:
dependency: transitive
description:
name: yaml
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
url: "https://pub.dev"
source: hosted
version: "3.1.3"
sdks:
dart: ">=3.7.2 <4.0.0"
flutter: ">=3.27.0"

96
pubspec.yaml Normal file
View File

@ -0,0 +1,96 @@
name: monitor2
description: "Monitor your URLs"
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.0
environment:
sdk: ^3.7.2
# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
# consider running `flutter pub upgrade --major-versions`. Alternatively,
# dependencies can be manually updated by changing the version numbers below to
# the latest version available on pub.dev. To see which dependencies have newer
# versions available, run `flutter pub outdated`.
dependencies:
flutter:
sdk: flutter
http: ^1.2.1
path_provider: ^2.1.2
flutter_launcher_icons: ^0.13.1
url_launcher: ^6.0.20
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.8
dev_dependencies:
flutter_test:
sdk: flutter
# The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^5.0.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter packages.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/to/resolution-aware-images
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/to/asset-from-package
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/to/font-from-package
flutter_icons:
android: true
image_path: "assets/icon.png"

29
test/widget_test.dart Normal file
View File

@ -0,0 +1,29 @@
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility in the flutter_test package. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:monitor2/monitor/monitor2app.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(const Monitor2App());
// Verify that our counter starts at 0.
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
// Tap the '+' icon and trigger a frame.
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
// Verify that our counter has incremented.
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
});
}