Compare commits
6
Commits
3c4c6f8222
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26ed1da54f | ||
|
|
9e356f8581 | ||
|
|
f0808047e3 | ||
|
|
423fa0efaa | ||
|
|
c8a3cc9812 | ||
|
|
9f7ee3f356 |
@@ -15,21 +15,6 @@ migration:
|
||||
- platform: root
|
||||
create_revision: c9a6c484230f8b5e408ec57be1ef71dee1e77020
|
||||
base_revision: c9a6c484230f8b5e408ec57be1ef71dee1e77020
|
||||
- platform: android
|
||||
create_revision: c9a6c484230f8b5e408ec57be1ef71dee1e77020
|
||||
base_revision: c9a6c484230f8b5e408ec57be1ef71dee1e77020
|
||||
- platform: ios
|
||||
create_revision: c9a6c484230f8b5e408ec57be1ef71dee1e77020
|
||||
base_revision: c9a6c484230f8b5e408ec57be1ef71dee1e77020
|
||||
- platform: linux
|
||||
create_revision: c9a6c484230f8b5e408ec57be1ef71dee1e77020
|
||||
base_revision: c9a6c484230f8b5e408ec57be1ef71dee1e77020
|
||||
- platform: macos
|
||||
create_revision: c9a6c484230f8b5e408ec57be1ef71dee1e77020
|
||||
base_revision: c9a6c484230f8b5e408ec57be1ef71dee1e77020
|
||||
- platform: web
|
||||
create_revision: c9a6c484230f8b5e408ec57be1ef71dee1e77020
|
||||
base_revision: c9a6c484230f8b5e408ec57be1ef71dee1e77020
|
||||
- platform: windows
|
||||
create_revision: c9a6c484230f8b5e408ec57be1ef71dee1e77020
|
||||
base_revision: c9a6c484230f8b5e408ec57be1ef71dee1e77020
|
||||
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Flutter Web Debug",
|
||||
"request": "launch",
|
||||
"type": "dart",
|
||||
"flutterMode": "debug",
|
||||
"args": [
|
||||
"--web-hostname=localhost",
|
||||
"--web-port=8080"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"cmake.sourceDirectory": "C:/Developement/FlutterFirma/flutter_test_services/windows"
|
||||
}
|
||||
@@ -7,6 +7,9 @@
|
||||
|
||||
# The following line activates a set of recommended lints for Flutter apps,
|
||||
# packages, and plugins designed to encourage good coding practices.
|
||||
analyzer:
|
||||
errors:
|
||||
avoid_print: warning
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
linter:
|
||||
@@ -21,7 +24,7 @@ linter:
|
||||
# `// 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
|
||||
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
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 208 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 207 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 210 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 203 KiB |
@@ -0,0 +1,322 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get_storage/get_storage.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
|
||||
import '../models/response_output.dart';
|
||||
import '../helper/constants.dart';
|
||||
|
||||
enum MainView { dashboard, traun, sarleinsbach, lannach, settings }
|
||||
|
||||
class HomeController extends GetxController {
|
||||
// Der Key, mit dem wir das Scaffold von hier aus steuern
|
||||
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
|
||||
final boxSettings = GetStorage();
|
||||
final currentView = MainView.dashboard.obs;
|
||||
|
||||
//--------------Settings View---------------------------
|
||||
final userWebMethodesController = TextEditingController().obs;
|
||||
final passwordWebMethodesController = TextEditingController().obs;
|
||||
|
||||
final powerUrlController = TextEditingController().obs;
|
||||
|
||||
void saveSettings() {
|
||||
String wbUser = userWebMethodesController.value.text;
|
||||
String wbPassword = passwordWebMethodesController.value.text;
|
||||
String wbPowerUrl = powerUrlController.value.text;
|
||||
|
||||
boxSettings.write('wbUser', wbUser);
|
||||
boxSettings.write('wbPassword', wbPassword);
|
||||
boxSettings.write('wbPowerUrl', wbPowerUrl);
|
||||
|
||||
kDisplaySnackBarGreen("Settings saved successfully!");
|
||||
|
||||
print('Einstellungen gespeichert:');
|
||||
print('Admin User: $wbUser');
|
||||
print('Admin Password: $wbPassword');
|
||||
print('Web Methodes Power URL: $wbPowerUrl');
|
||||
}
|
||||
//------------------------------------------------------
|
||||
// http get request to fetch data from the provided URL
|
||||
//------------------------------------------------------
|
||||
|
||||
final dateFromToIsoController = TextEditingController().obs;
|
||||
final dateToIsoController = TextEditingController().obs;
|
||||
final inputSwitchBranches = RxnString('TraunPV');
|
||||
final responseOutputTraunPV = ResponseOutput().obs;
|
||||
final responseOutputTraunImport = ResponseOutput().obs;
|
||||
final responseOutputSarleinsbachPV = ResponseOutput().obs;
|
||||
final responseOutputSarleinsbachImport = ResponseOutput().obs;
|
||||
final responseOutputLannachPV = ResponseOutput().obs;
|
||||
final responseOutputLannachImport = ResponseOutput().obs;
|
||||
|
||||
/// Map: Branch → (PV Observable, Import Observable)
|
||||
Map<String, Map<String, dynamic>> get _branchConfig => {
|
||||
'TraunPV': {
|
||||
'pv': responseOutputTraunPV,
|
||||
'import': responseOutputTraunImport,
|
||||
'pvSuffix': 'TraunPV',
|
||||
'importSuffix': 'TraunImport',
|
||||
},
|
||||
'TraunImport': {
|
||||
'pv': responseOutputTraunPV,
|
||||
'import': responseOutputTraunImport,
|
||||
'pvSuffix': 'TraunPV',
|
||||
'importSuffix': 'TraunImport',
|
||||
},
|
||||
'SarleinsbachPV': {
|
||||
'pv': responseOutputSarleinsbachPV,
|
||||
'import': responseOutputSarleinsbachImport,
|
||||
'pvSuffix': 'SarleinsbachPV',
|
||||
'importSuffix': 'SarleinsbachImport',
|
||||
},
|
||||
'SarleinsbachImport': {
|
||||
'pv': responseOutputSarleinsbachPV,
|
||||
'import': responseOutputSarleinsbachImport,
|
||||
'pvSuffix': 'SarleinsbachPV',
|
||||
'importSuffix': 'SarleinsbachImport',
|
||||
},
|
||||
'LannachPV': {
|
||||
'pv': responseOutputLannachPV,
|
||||
'import': responseOutputLannachImport,
|
||||
'pvSuffix': 'LannachPV',
|
||||
'importSuffix': 'LannachImport',
|
||||
},
|
||||
'LannachImport': {
|
||||
'pv': responseOutputLannachPV,
|
||||
'import': responseOutputLannachImport,
|
||||
'pvSuffix': 'LannachPV',
|
||||
'importSuffix': 'LannachImport',
|
||||
},
|
||||
};
|
||||
|
||||
//Device Info data
|
||||
Future<bool> isAndroidSimulator() async {
|
||||
// Prüfen, ob es überhaupt Android ist
|
||||
if (!Platform.isAndroid) return false;
|
||||
|
||||
final deviceInfo = DeviceInfoPlugin();
|
||||
final androidInfo = await deviceInfo.androidInfo;
|
||||
|
||||
// Wenn es KEIN physisches Gerät ist, ist es ein Simulator/Emulator
|
||||
return !androidInfo.isPhysicalDevice;
|
||||
}
|
||||
|
||||
void fetchData() async {
|
||||
final inputFromIso = dateFromToIsoController.value.text;
|
||||
final inputToIso = dateToIsoController.value.text;
|
||||
final branch = inputSwitchBranches.value;
|
||||
|
||||
if (branch == null || branch.isEmpty) {
|
||||
kDisplaySnackBarRed('Ungültiger Standort ausgewählt.');
|
||||
return;
|
||||
}
|
||||
|
||||
final baseUrl = getBaseUrl;
|
||||
if (baseUrl.isEmpty) {
|
||||
kDisplaySnackBarRed('Bitte zuerst die Server-URL eintragen.');
|
||||
return;
|
||||
}
|
||||
|
||||
final config = _branchConfig[branch];
|
||||
if (config == null) {
|
||||
kDisplaySnackBarRed('Unbekannte Branche: $branch');
|
||||
return;
|
||||
}
|
||||
|
||||
final credentials =
|
||||
'${userWebMethodesController.value.text}:${passwordWebMethodesController.value.text}';
|
||||
final basicAuth = 'Basic ${base64Encode(utf8.encode(credentials))}';
|
||||
final baseUri = Uri.parse(baseUrl);
|
||||
|
||||
try {
|
||||
// Fetch PV Daten
|
||||
await _fetchAndStore(
|
||||
baseUri,
|
||||
inputFromIso,
|
||||
inputToIso,
|
||||
config['pvSuffix'],
|
||||
config['pv'],
|
||||
basicAuth,
|
||||
);
|
||||
|
||||
// Fetch Import Daten
|
||||
await _fetchAndStore(
|
||||
baseUri,
|
||||
inputFromIso,
|
||||
inputToIso,
|
||||
config['importSuffix'],
|
||||
config['import'],
|
||||
basicAuth,
|
||||
);
|
||||
} catch (e) {
|
||||
print('Error: $e');
|
||||
kDisplaySnackBarRed('Netzwerkfehler: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Hilfsfunktion - reduziert Codeverdoppelung
|
||||
Future<void> _fetchAndStore(
|
||||
Uri baseUri,
|
||||
String inputFromIso,
|
||||
String inputToIso,
|
||||
String switchBranch,
|
||||
dynamic responseObservable,
|
||||
String basicAuth,
|
||||
) async {
|
||||
final uri = baseUri.replace(
|
||||
queryParameters: {
|
||||
...baseUri.queryParameters,
|
||||
'InputFromIso': inputFromIso,
|
||||
'InputToIso': inputToIso,
|
||||
'InputSwitchBranches': switchBranch,
|
||||
},
|
||||
);
|
||||
|
||||
try {
|
||||
final response = await http.get(
|
||||
uri,
|
||||
headers: {'Authorization': basicAuth, 'Accept': 'application/json'},
|
||||
);
|
||||
|
||||
final statusGroup = response.statusCode ~/ 100;
|
||||
|
||||
if (statusGroup == 2) {
|
||||
print('✓ $switchBranch erfolgreich geladen');
|
||||
responseObservable.value = ResponseOutput.fromJson(
|
||||
jsonDecode(response.body),
|
||||
);
|
||||
} else if (statusGroup == 4) {
|
||||
kDisplaySnackBarRed('Fehler 4xx: ${response.statusCode}');
|
||||
} else if (statusGroup == 5) {
|
||||
kDisplaySnackBarRed('Fehler 5xx: ${response.statusCode}');
|
||||
} else {
|
||||
kDisplaySnackBarRed('Fehler: ${response.statusCode}');
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error fetching $switchBranch: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
final isEmulator = false.obs;
|
||||
|
||||
// Synchroner Getter
|
||||
String get getBaseUrl {
|
||||
if (kIsWeb) {
|
||||
if (kDebugMode) {
|
||||
// Lokale Entwicklung mit lokalem Proxy
|
||||
return 'http://localhost:3000/invoke/IFN_ASKI_Service.flows/getAskiData?';
|
||||
} else {
|
||||
// Produktion: Direkt an den Server oder über den Produktions-Proxy
|
||||
return 'http://localhost:3000/invoke/IFN_ASKI_Service.flows/getAskiData?';
|
||||
// ODER bei Nginx-Proxy: '/api/IFN_ASKI_Service.flows/getAskiData?'
|
||||
}
|
||||
}
|
||||
|
||||
if (isEmulator.value) {
|
||||
return 'http://10.12.101.27:5556/invoke/IFN_ASKI_Service.flows/getAskiData?';
|
||||
}
|
||||
|
||||
return powerUrlController.value.text.trim();
|
||||
}
|
||||
|
||||
/// Wählt die richtige Base-URL:
|
||||
/// Web: localhost:3000 (Reverse Proxy)
|
||||
/// Desktop: Direkt von Settings
|
||||
// Future<String> _getBaseUrl() async {
|
||||
// final settingsUrl = powerUrlController.value.text.trim();
|
||||
|
||||
// // Auf Web: verwende Reverse Proxy auf localhost:3000
|
||||
// if (kIsWeb) {
|
||||
// return 'http://localhost:3000/invoke/IFN_ASKI_Service.flows/getAskiData?';
|
||||
// }
|
||||
// if (await isAndroidSimulator()) {
|
||||
// return 'http://10.12.101.27:5556/invoke/IFN_ASKI_Service.flows/getAskiData?';
|
||||
// }
|
||||
|
||||
// // Auf Desktop (Windows, Linux, macOS): direkt von Settings
|
||||
// return settingsUrl;
|
||||
// }
|
||||
|
||||
void changeView(MainView view) {
|
||||
currentView.value = view;
|
||||
if (currentView.value == MainView.dashboard) {
|
||||
inputSwitchBranches.value = 'TraunPV';
|
||||
} else if (currentView.value == MainView.traun) {
|
||||
inputSwitchBranches.value = 'TraunPV';
|
||||
} else if (currentView.value == MainView.sarleinsbach) {
|
||||
inputSwitchBranches.value = 'SarleinsbachPV';
|
||||
} else if (currentView.value == MainView.lannach) {
|
||||
inputSwitchBranches.value = 'LannachPV';
|
||||
}
|
||||
if (currentView.value != MainView.dashboard) {
|
||||
fetchData(); // Fetch data whenever the view changes
|
||||
}
|
||||
}
|
||||
|
||||
void toggleDrawer() {
|
||||
final ScaffoldState? state = scaffoldKey.currentState;
|
||||
|
||||
if (state != null) {
|
||||
if (state.isDrawerOpen) {
|
||||
print("Schließe Drawer...");
|
||||
state.closeDrawer(); // Wartet auf das Ende der Schließ-Animation
|
||||
print("Drawer geschlossen.");
|
||||
} else {
|
||||
print("Öffne Drawer...");
|
||||
state.openDrawer(); // Wartet auf das Ende der Öffnen-Animation
|
||||
print("Drawer geöffnet.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onInit() async {
|
||||
super.onInit();
|
||||
if (!kIsWeb && Platform.isAndroid) {
|
||||
final deviceInfo = DeviceInfoPlugin();
|
||||
final androidInfo = await deviceInfo.androidInfo;
|
||||
isEmulator(!androidInfo.isPhysicalDevice);
|
||||
}
|
||||
_readStorageData();
|
||||
}
|
||||
|
||||
void _readStorageData() {
|
||||
bool hasWbUser = boxSettings.hasData('wbUser');
|
||||
if (hasWbUser) {
|
||||
userWebMethodesController.value.text = boxSettings.read('wbUser');
|
||||
}
|
||||
bool hasWbPassword = boxSettings.hasData('wbPassword');
|
||||
if (hasWbPassword) {
|
||||
passwordWebMethodesController.value.text = boxSettings.read('wbPassword');
|
||||
}
|
||||
bool hasWbPowerUrl = boxSettings.hasData('wbPowerUrl');
|
||||
if (hasWbPowerUrl) {
|
||||
powerUrlController.value.text = boxSettings.read('wbPowerUrl');
|
||||
}
|
||||
//fromDateTimeIso and toDateTimeIso
|
||||
dateFromToIsoController.value.text = DateTime(
|
||||
DateTime.now().year,
|
||||
DateTime.now().month,
|
||||
DateTime.now().day,
|
||||
).toIso8601String();
|
||||
dateToIsoController.value.text = DateTime.now().toIso8601String();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
userWebMethodesController.close();
|
||||
powerUrlController.close();
|
||||
passwordWebMethodesController.close();
|
||||
dateFromToIsoController.close();
|
||||
dateToIsoController.close();
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
var kFontSizeDouble = 15.0;
|
||||
|
||||
var kTextSyleLittleGrey = TextStyle(
|
||||
fontSize: 12.0,
|
||||
color: Colors.grey.shade800,
|
||||
);
|
||||
|
||||
var kTextSyleHeaderGrey = TextStyle(
|
||||
fontSize: 25.0,
|
||||
color: Colors.grey.shade800,
|
||||
);
|
||||
|
||||
var kElevatetButtonStyleDrawer = ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.blueGrey,
|
||||
foregroundColor: Colors.white,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||
textStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
||||
);
|
||||
|
||||
//DropDown Styles
|
||||
var kInputDecorationDropDownMenue = InputDecoration(
|
||||
//prefixIcon: Icon(Icons.date_range),
|
||||
hintText: 'User'.toUpperCase(),
|
||||
contentPadding: const EdgeInsets.all(10),
|
||||
hintStyle: TextStyle(letterSpacing: 2, fontSize: kFontSizeDouble),
|
||||
filled: true,
|
||||
fillColor: Colors.grey.shade400,
|
||||
errorStyle: const TextStyle(color: Colors.yellow),
|
||||
);
|
||||
|
||||
SnackbarController kDisplaySnackBarRed(String szInfoText) {
|
||||
return Get.snackbar(
|
||||
'Info',
|
||||
szInfoText,
|
||||
backgroundColor: Colors.red[600],
|
||||
snackPosition: SnackPosition.TOP,
|
||||
colorText: Colors.white,
|
||||
snackStyle: SnackStyle.GROUNDED,
|
||||
);
|
||||
}
|
||||
|
||||
SnackbarController kDisplaySnackBarGreen(String szInfoText) {
|
||||
return Get.snackbar(
|
||||
'Info',
|
||||
szInfoText,
|
||||
backgroundColor: Colors.green[600],
|
||||
snackPosition: SnackPosition.TOP,
|
||||
colorText: Colors.black,
|
||||
snackStyle: SnackStyle.GROUNDED,
|
||||
);
|
||||
}
|
||||
|
||||
//Setting Wait for Delete
|
||||
List<Map<String, dynamic>> kListMapSetting = [
|
||||
{'ContainerID': '', 'Info': ''},
|
||||
];
|
||||
|
||||
//Switching PROD/DEV
|
||||
String kStringEnvironment = '?';
|
||||
|
||||
Future<String?> kShowPopupDialog(
|
||||
String title,
|
||||
String content,
|
||||
String buttonLeftText,
|
||||
String buttonRightText,
|
||||
) async {
|
||||
return await Get.dialog<String>(
|
||||
AlertDialog(
|
||||
title: Text(title),
|
||||
content: Text(content),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(Get.overlayContext!).pop('Abbrechen');
|
||||
},
|
||||
child: Text(buttonLeftText),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(Get.overlayContext!).pop('OK');
|
||||
},
|
||||
child: Text(buttonRightText),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import 'dart:io';
|
||||
|
||||
class MyHttpOverrides extends HttpOverrides {
|
||||
@override
|
||||
HttpClient createHttpClient(SecurityContext? context) {
|
||||
return super.createHttpClient(context)
|
||||
..badCertificateCallback =
|
||||
(X509Certificate cert, String host, int port) => true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
|
||||
import 'package:get/get.dart';
|
||||
import '../controller/home_controller.dart';
|
||||
|
||||
class SampleBindings extends Bindings {
|
||||
@override
|
||||
void dependencies() {
|
||||
Get.lazyPut<HomeController>(() => HomeController());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../pages/home/home_view.dart';
|
||||
import './sample_bindings.dart';
|
||||
|
||||
class SampleRouts {
|
||||
static final sampleBindings = SampleBindings();
|
||||
static final samplePages = [
|
||||
GetPage(
|
||||
name: HomePage.routeName,
|
||||
binding: sampleBindings,
|
||||
page: () => const HomePage(),
|
||||
transition: Transition.leftToRight,
|
||||
),
|
||||
];
|
||||
}
|
||||
+20
-106
@@ -1,6 +1,18 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
void main() {
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get_storage/get_storage.dart';
|
||||
|
||||
import 'helper/http_overrides.dart';
|
||||
import 'helper/sample_routes.dart';
|
||||
import 'pages/home/home_view.dart';
|
||||
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
await GetStorage.init();
|
||||
HttpOverrides.global = MyHttpOverrides();
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
@@ -10,113 +22,15 @@ class MyApp extends StatelessWidget {
|
||||
// This widget is the root of your application.
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
return GetMaterialApp(
|
||||
title: 'Flutter Demo',
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: ThemeData(
|
||||
// This is the theme of your application.
|
||||
//
|
||||
// TRY THIS: Try running your application with "flutter run". You'll see
|
||||
// the application has a purple toolbar. Then, without quitting the app,
|
||||
// try changing the seedColor in the colorScheme below to Colors.green
|
||||
// and then invoke "hot reload" (save your changes or press the "hot
|
||||
// reload" button in a Flutter-supported IDE, or press "r" if you used
|
||||
// the command line to start the app).
|
||||
//
|
||||
// Notice that the counter didn't reset back to zero; the application
|
||||
// state is not lost during the reload. To reset the state, use hot
|
||||
// restart instead.
|
||||
//
|
||||
// This works for code too, not just values: Most code changes can be
|
||||
// tested with just a hot reload.
|
||||
colorScheme: .fromSeed(seedColor: Colors.deepPurple),
|
||||
),
|
||||
home: const MyHomePage(title: 'Flutter Demo Home Page'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyHomePage extends StatefulWidget {
|
||||
const MyHomePage({super.key, required this.title});
|
||||
|
||||
// This widget is the home page of your application. It is stateful, meaning
|
||||
// that it has a State object (defined below) that contains fields that affect
|
||||
// how it looks.
|
||||
|
||||
// This class is the configuration for the state. It holds the values (in this
|
||||
// case the title) provided by the parent (in this case the App widget) and
|
||||
// used by the build method of the State. Fields in a Widget subclass are
|
||||
// always marked "final".
|
||||
|
||||
final String title;
|
||||
|
||||
@override
|
||||
State<MyHomePage> createState() => _MyHomePageState();
|
||||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> {
|
||||
int _counter = 0;
|
||||
|
||||
void _incrementCounter() {
|
||||
setState(() {
|
||||
// This call to setState tells the Flutter framework that something has
|
||||
// changed in this State, which causes it to rerun the build method below
|
||||
// so that the display can reflect the updated values. If we changed
|
||||
// _counter without calling setState(), then the build method would not be
|
||||
// called again, and so nothing would appear to happen.
|
||||
_counter++;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// This method is rerun every time setState is called, for instance as done
|
||||
// by the _incrementCounter method above.
|
||||
//
|
||||
// The Flutter framework has been optimized to make rerunning build methods
|
||||
// fast, so that you can just rebuild anything that needs updating rather
|
||||
// than having to individually change instances of widgets.
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
// TRY THIS: Try changing the color here to a specific color (to
|
||||
// Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
|
||||
// change color while the other colors stay the same.
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
// Here we take the value from the MyHomePage object that was created by
|
||||
// the App.build method, and use it to set our appbar title.
|
||||
title: Text(widget.title),
|
||||
),
|
||||
body: Center(
|
||||
// Center is a layout widget. It takes a single child and positions it
|
||||
// in the middle of the parent.
|
||||
child: Column(
|
||||
// Column is also a layout widget. It takes a list of children and
|
||||
// arranges them vertically. By default, it sizes itself to fit its
|
||||
// children horizontally, and tries to be as tall as its parent.
|
||||
//
|
||||
// Column has various properties to control how it sizes itself and
|
||||
// how it positions its children. Here we use mainAxisAlignment to
|
||||
// center the children vertically; the main axis here is the vertical
|
||||
// axis because Columns are vertical (the cross axis would be
|
||||
// horizontal).
|
||||
//
|
||||
// TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint"
|
||||
// action in the IDE, or press "p" in the console), to see the
|
||||
// wireframe for each widget.
|
||||
mainAxisAlignment: .center,
|
||||
children: [
|
||||
const Text('You have pushed the button this many times:'),
|
||||
Text(
|
||||
'$_counter',
|
||||
style: Theme.of(context).textTheme.headlineMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: _incrementCounter,
|
||||
tooltip: 'Increment',
|
||||
child: const Icon(Icons.add),
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blueGrey),
|
||||
),
|
||||
|
||||
initialRoute: HomePage.routeName,
|
||||
getPages: SampleRouts.samplePages,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
class ResponseOutput {
|
||||
DataResult? dataResult;
|
||||
|
||||
ResponseOutput({this.dataResult});
|
||||
|
||||
ResponseOutput.fromJson(Map<String, dynamic> json) {
|
||||
dataResult = json['DataResult'] != null
|
||||
? DataResult.fromJson(json['DataResult'])
|
||||
: null;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
if (dataResult != null) {
|
||||
data['DataResult'] = dataResult!.toJson();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class DataResult {
|
||||
String? httpStatus;
|
||||
String? orderType;
|
||||
String? location;
|
||||
int? meterId;
|
||||
List<Values>? values;
|
||||
|
||||
DataResult(
|
||||
{this.httpStatus,
|
||||
this.orderType,
|
||||
this.location,
|
||||
this.meterId,
|
||||
this.values});
|
||||
|
||||
DataResult.fromJson(Map<String, dynamic> json) {
|
||||
httpStatus = json['HttpStatus'];
|
||||
orderType = json['OrderType'];
|
||||
location = json['Location'];
|
||||
meterId = json['meterId'];
|
||||
if (json['values'] != null) {
|
||||
values = <Values>[];
|
||||
json['values'].forEach((v) {
|
||||
values!.add(Values.fromJson(v));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['HttpStatus'] = httpStatus;
|
||||
data['OrderType'] = orderType;
|
||||
data['Location'] = location;
|
||||
data['meterId'] = meterId;
|
||||
if (values != null) {
|
||||
data['values'] = values!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Values {
|
||||
String? datetime;
|
||||
double? value;
|
||||
Null tariff;
|
||||
|
||||
Values({this.datetime, this.value, this.tariff});
|
||||
|
||||
Values.fromJson(Map<String, dynamic> json) {
|
||||
datetime = json['datetime'];
|
||||
value = (json['value'] as num?)?.toDouble();
|
||||
tariff = json['tariff'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['datetime'] = datetime;
|
||||
data['value'] = value;
|
||||
data['tariff'] = tariff;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../../controller/home_controller.dart';
|
||||
import '../../widgets/drawer_widget.dart';
|
||||
import '../../widgets/views/dashboard.dart';
|
||||
import '../../widgets/views/lannach.dart';
|
||||
import '../../widgets/views/sarleinsbach.dart';
|
||||
import '../../widgets/views/settings.dart';
|
||||
import '../../widgets/views/traun.dart';
|
||||
|
||||
class HomePage extends GetView<HomeController> {
|
||||
static const String routeName = '/home-page';
|
||||
const HomePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var hCtrl = controller;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('ASKI Internorm Inside'),
|
||||
backgroundColor: Colors.blueGrey,
|
||||
foregroundColor: Colors.white,
|
||||
toolbarHeight: 80,
|
||||
iconTheme: const IconThemeData(size: 40, color: Colors.white),
|
||||
titleTextStyle: const TextStyle(fontSize: 35, color: Colors.white),
|
||||
),
|
||||
drawer: const Drawer(child: DrawerWidget()),
|
||||
body: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[300]
|
||||
),
|
||||
child: Obx(() {
|
||||
switch (hCtrl.currentView.value) {
|
||||
case MainView.dashboard:
|
||||
return const DashboardView();
|
||||
case MainView.traun:
|
||||
return const TraunView();
|
||||
case MainView.sarleinsbach:
|
||||
return const SarleinsbachView();
|
||||
case MainView.lannach:
|
||||
return const LannachView();
|
||||
case MainView.settings:
|
||||
return const SettingsView();
|
||||
}
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,437 @@
|
||||
import 'package:fl_chart/fl_chart.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../models/response_output.dart';
|
||||
|
||||
/// Wiederverwendbares Balkendiagramm Widget für PV/Import Vergleich
|
||||
///
|
||||
/// Zeigt zwei Datensätze (z.B. TraunPV + TraunImport) als nebeneinander angeordnete Balken
|
||||
/// - PV Daten in Orange
|
||||
/// - Import Daten in Rot
|
||||
/// - Y-Achse: kW Werte
|
||||
/// - X-Achse: Datetime (als Uhrzeit angezeigt)
|
||||
class ComparisonBarChart extends StatelessWidget {
|
||||
final ResponseOutput pvData;
|
||||
final ResponseOutput importData;
|
||||
final String title;
|
||||
|
||||
const ComparisonBarChart({
|
||||
required this.pvData,
|
||||
required this.importData,
|
||||
required this.title,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final pvValues = pvData.dataResult?.values ?? [];
|
||||
final importValues = importData.dataResult?.values ?? [];
|
||||
|
||||
// Erstelle eine Map mit datetime als Schlüssel
|
||||
final Map<String, double> pvMap = {
|
||||
for (var v in pvValues) (v.datetime ?? ''): (v.value ?? 0.0),
|
||||
};
|
||||
final Map<String, double> importMap = {
|
||||
for (var v in importValues) (v.datetime ?? ''): (v.value ?? 0.0),
|
||||
};
|
||||
|
||||
// Alle eindeutigen datetimes sammeln und sortieren
|
||||
final allDatetimes = {...pvMap.keys, ...importMap.keys}.toList();
|
||||
allDatetimes.sort();
|
||||
|
||||
// Begrenzen auf die letzten 20 Einträge für bessere Lesbarkeit
|
||||
// final displayDatetimes = allDatetimes.length > 20
|
||||
// ? allDatetimes.sublist(allDatetimes.length - 20)
|
||||
// : allDatetimes;
|
||||
final displayDatetimes = allDatetimes;
|
||||
|
||||
if (displayDatetimes.isEmpty) {
|
||||
return const Center(child: Text('Keine Daten verfügbar'));
|
||||
}
|
||||
|
||||
// Berechne Maximalwert
|
||||
final allValues = [...pvMap.values, ...importMap.values];
|
||||
final maxValue = allValues.fold(0.0, (a, b) => a > b ? a : b);
|
||||
|
||||
// Maxima für PV und Import separat
|
||||
double maxPvValue = 0;
|
||||
int maxPvIndex = 0;
|
||||
double maxImportValue = 0;
|
||||
int maxImportIndex = 0;
|
||||
|
||||
for (int i = 0; i < displayDatetimes.length; i++) {
|
||||
final dt = displayDatetimes[i];
|
||||
final pv = pvMap[dt] ?? 0.0;
|
||||
final imp = importMap[dt] ?? 0.0;
|
||||
|
||||
if (pv > maxPvValue) {
|
||||
maxPvValue = pv;
|
||||
maxPvIndex = i;
|
||||
}
|
||||
if (imp > maxImportValue) {
|
||||
maxImportValue = imp;
|
||||
maxImportIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
return SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 26.0,
|
||||
right: 35.0,
|
||||
top: 16.0,
|
||||
bottom: 16.0,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
title,
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
// Chart mit fester Höhe
|
||||
SizedBox(
|
||||
height: 500,
|
||||
child: BarChart(
|
||||
BarChartData(
|
||||
barTouchData: BarTouchData(
|
||||
enabled: true,
|
||||
touchTooltipData: BarTouchTooltipData(
|
||||
// Optional: Hintergrundfarbe und Styling des Tooltips anpassen
|
||||
getTooltipItem: (group, groupIndex, rod, rodIndex) {
|
||||
// 1. Datum/Uhrzeit anhand des groupIndex abrufen
|
||||
final rawDateTime = displayDatetimes[groupIndex];
|
||||
|
||||
// 2. Formatieren zu "20.07.26 12:00"
|
||||
String formattedDateTime = rawDateTime;
|
||||
try {
|
||||
final parsedDate = DateTime.parse(rawDateTime);
|
||||
final day = parsedDate.day.toString().padLeft(2, '0');
|
||||
final month = parsedDate.month.toString().padLeft(
|
||||
2,
|
||||
'0',
|
||||
);
|
||||
final year = parsedDate.year.toString().substring(2);
|
||||
final hour = parsedDate.hour.toString().padLeft(
|
||||
2,
|
||||
'0',
|
||||
);
|
||||
final minute = parsedDate.minute.toString().padLeft(
|
||||
2,
|
||||
'0',
|
||||
);
|
||||
formattedDateTime = '$day.$month.$year $hour:$minute';
|
||||
} catch (_) {}
|
||||
|
||||
// 3. Typ bestimmen (z.B. PV oder Import je nach Rod-Index)
|
||||
final label = rodIndex == 0 ? 'PV' : 'Import';
|
||||
final unit = 'kW';
|
||||
|
||||
// 4. Nur beim ersten Ballekn der Gruppe das Datum als Header einfügen
|
||||
// (sonst würde es bei jedem Einzelbalken doppelt stehen)
|
||||
return BarTooltipItem(
|
||||
'$formattedDateTime\n$label: ${rod.toY.round()} $unit',
|
||||
const TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
alignment: BarChartAlignment.spaceAround,
|
||||
maxY: maxValue * 1.02,
|
||||
minY: 0,
|
||||
gridData: FlGridData(
|
||||
show: true,
|
||||
drawVerticalLine: false,
|
||||
horizontalInterval: maxValue * 0.2,
|
||||
),
|
||||
titlesData: FlTitlesData(
|
||||
show: true,
|
||||
topTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
showTitles: true,
|
||||
reservedSize: 40,
|
||||
getTitlesWidget: (value, meta) {
|
||||
final index = value.toInt();
|
||||
|
||||
// PV Maximum - oranger Pin
|
||||
if (index == maxPvIndex) {
|
||||
return Transform.translate(
|
||||
offset: const Offset(0, 0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.orange,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withValues(
|
||||
alpha: 0.3,
|
||||
),
|
||||
blurRadius: 4,
|
||||
),
|
||||
],
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 6,
|
||||
),
|
||||
child: Text(
|
||||
maxPvValue.toStringAsFixed(0),
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
// Pin nach unten
|
||||
CustomPaint(
|
||||
size: const Size(20, 10),
|
||||
painter: PinPainter(Colors.orange),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Import Maximum - roter Pin
|
||||
if (index == maxImportIndex) {
|
||||
return Transform.translate(
|
||||
offset: const Offset(3, 0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withValues(
|
||||
alpha: 0.3,
|
||||
),
|
||||
blurRadius: 4,
|
||||
),
|
||||
],
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 6,
|
||||
),
|
||||
child: Text(
|
||||
maxImportValue.toStringAsFixed(0),
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
// Pin nach unten
|
||||
CustomPaint(
|
||||
size: const Size(20, 10),
|
||||
painter: PinPainter(Colors.red),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return const SizedBox();
|
||||
},
|
||||
),
|
||||
),
|
||||
rightTitles: AxisTitles(
|
||||
sideTitles: SideTitles(showTitles: false),
|
||||
),
|
||||
leftTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
showTitles: true,
|
||||
reservedSize: 50,
|
||||
getTitlesWidget: (value, meta) {
|
||||
return Text(
|
||||
'${value.toInt()} kW',
|
||||
style: const TextStyle(fontSize: 12),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
bottomTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
showTitles: true,
|
||||
reservedSize: 40, // Platz für die normale Textzeile
|
||||
getTitlesWidget: (value, meta) {
|
||||
final index = value.toInt();
|
||||
if (index < 0 || index >= displayDatetimes.length) {
|
||||
return const SizedBox();
|
||||
}
|
||||
|
||||
// 1. Indizes für Start, Mitte und Ende bestimmen
|
||||
final firstIndex = 0;
|
||||
final lastIndex = displayDatetimes.length - 1;
|
||||
final middleIndex = displayDatetimes.length ~/ 2;
|
||||
|
||||
// 2. Nur anzeigen, wenn es Start, Mitte oder Ende ist
|
||||
final isFirst = index == firstIndex;
|
||||
final isMiddle =
|
||||
index == middleIndex &&
|
||||
displayDatetimes.length > 2;
|
||||
final isLast =
|
||||
index == lastIndex && displayDatetimes.length > 1;
|
||||
|
||||
if (!isFirst && !isMiddle && !isLast) {
|
||||
return const SizedBox(); // Für alle anderen Balken ausblenden
|
||||
}
|
||||
|
||||
final datetimeRaw = displayDatetimes[index];
|
||||
|
||||
// 3. Formatiere den String zu "DD.MM.YY HH:mm"
|
||||
String formattedDateTime = datetimeRaw;
|
||||
try {
|
||||
final parsedDate = DateTime.parse(datetimeRaw);
|
||||
final day = parsedDate.day.toString().padLeft(
|
||||
2,
|
||||
'0',
|
||||
);
|
||||
final month = parsedDate.month.toString().padLeft(
|
||||
2,
|
||||
'0',
|
||||
);
|
||||
final year = parsedDate.year.toString().substring(
|
||||
2,
|
||||
); // Die letzten 2 Stellen
|
||||
final hour = parsedDate.hour.toString().padLeft(
|
||||
2,
|
||||
'0',
|
||||
);
|
||||
final minute = parsedDate.minute.toString().padLeft(
|
||||
2,
|
||||
'0',
|
||||
);
|
||||
|
||||
formattedDateTime =
|
||||
'$day.$month.$year $hour:$minute';
|
||||
} catch (_) {
|
||||
// Fallback, falls String kein echtes ISO-Format ist
|
||||
formattedDateTime = datetimeRaw;
|
||||
}
|
||||
|
||||
// 4. Liegend (horizontal) ausgeben
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
formattedDateTime,
|
||||
style: const TextStyle(
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
barGroups: _generateBarGroups(
|
||||
displayDatetimes,
|
||||
pvMap,
|
||||
importMap,
|
||||
),
|
||||
borderData: FlBorderData(show: true),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
// Legende
|
||||
Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 24,
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(width: 16, height: 16, color: Colors.orange),
|
||||
const SizedBox(width: 8),
|
||||
const Text('PV-Anlage(kW)'),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(width: 16, height: 16, color: Colors.red),
|
||||
const SizedBox(width: 8),
|
||||
const Text('Netzbezug(kW)'),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
List<BarChartGroupData> _generateBarGroups(
|
||||
List<String> datetimes,
|
||||
Map<String, double> pvMap,
|
||||
Map<String, double> importMap,
|
||||
) {
|
||||
return List.generate(datetimes.length, (index) {
|
||||
final datetime = datetimes[index];
|
||||
final pvValue = pvMap[datetime] ?? 0.0;
|
||||
final importValue = importMap[datetime] ?? 0.0;
|
||||
|
||||
return BarChartGroupData(
|
||||
x: index,
|
||||
barRods: [
|
||||
// Orange Bar für PV
|
||||
BarChartRodData(
|
||||
toY: pvValue,
|
||||
color: Colors.orange,
|
||||
width: 5, // <-- ERHEBLICH SCHMALER (z.B. 2 oder 3 statt 6/8)
|
||||
borderRadius: const BorderRadius.vertical(top: Radius.circular(1)),
|
||||
),
|
||||
// Roter Bar für Import
|
||||
BarChartRodData(
|
||||
toY: importValue,
|
||||
color: Colors.red,
|
||||
width: 5, // <-- ERHEBLICH SCHMALER
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(2.5),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class PinPainter extends CustomPainter {
|
||||
final Color color;
|
||||
|
||||
PinPainter(this.color);
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final paint = Paint()..color = color;
|
||||
final path = Path();
|
||||
path.moveTo(size.width / 2, size.height);
|
||||
path.lineTo(0, 0);
|
||||
path.lineTo(size.width, 0);
|
||||
path.close();
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(PinPainter oldDelegate) => false;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../controller/home_controller.dart';
|
||||
import '../helper/constants.dart';
|
||||
import './my_elevated_button_style_drawer.dart';
|
||||
|
||||
class DrawerWidget extends StatelessWidget {
|
||||
const DrawerWidget({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 30.0),
|
||||
child: Column(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text('Drawer Widget', textAlign: TextAlign.center, style: kTextSyleHeaderGrey),
|
||||
SizedBox(height: 50),
|
||||
MyElevatedButtonStyleDrawer(
|
||||
buttonText: 'Dashboard',
|
||||
onPressed: () {
|
||||
Get.find<HomeController>().changeView(MainView.dashboard);
|
||||
Get.close(1);
|
||||
},
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
MyElevatedButtonStyleDrawer(
|
||||
buttonText: 'Traun',
|
||||
onPressed: () {
|
||||
Get.find<HomeController>().changeView(MainView.traun);
|
||||
Get.close(1);
|
||||
},
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
MyElevatedButtonStyleDrawer(
|
||||
buttonText: 'Sarleinsbach',
|
||||
onPressed: () {
|
||||
Get.find<HomeController>().changeView(MainView.sarleinsbach);
|
||||
Get.close(1);
|
||||
},
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
MyElevatedButtonStyleDrawer(
|
||||
buttonText: 'Lannach',
|
||||
onPressed: () {
|
||||
Get.find<HomeController>().changeView(MainView.lannach);
|
||||
Get.close(1);
|
||||
},
|
||||
),
|
||||
SizedBox(height: 60),
|
||||
MyElevatedButtonStyleDrawer(
|
||||
buttonText: 'Settings',
|
||||
onPressed: () {
|
||||
Get.find<HomeController>().changeView(MainView.settings);
|
||||
Get.close(1);
|
||||
},
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
SizedBox(
|
||||
width: 200,
|
||||
height: 40,
|
||||
child: ElevatedButton(
|
||||
style: kElevatetButtonStyleDrawer,
|
||||
onPressed: () {
|
||||
Get.close(1);
|
||||
},
|
||||
child: Text('Close'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../helper/constants.dart';
|
||||
|
||||
class MyElevatedButtonStyleDrawer extends StatelessWidget {
|
||||
const MyElevatedButtonStyleDrawer({super.key, this.onPressed, required this.buttonText});
|
||||
|
||||
final void Function()? onPressed;
|
||||
final String buttonText;
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: 200,
|
||||
height: 40,
|
||||
child: ElevatedButton(
|
||||
style: kElevatetButtonStyleDrawer,
|
||||
onPressed: onPressed,
|
||||
child: Text(buttonText),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class StaticLocationDropdown extends StatelessWidget {
|
||||
const StaticLocationDropdown({super.key, required this.selectedValue});
|
||||
|
||||
final RxnString selectedValue;
|
||||
|
||||
static const List<String> _locations = [
|
||||
'TraunPV',
|
||||
'TraunImport',
|
||||
'SarleinsbachPV',
|
||||
'SarleinsbachImport',
|
||||
'LannachPV',
|
||||
'LannachImport',
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Obx(() => DropdownButtonFormField<String>(
|
||||
initialValue: selectedValue.value ?? _locations.first,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Select Location / Data Source',
|
||||
border: OutlineInputBorder(),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 15),
|
||||
),
|
||||
items: _locations.map((String location) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: location,
|
||||
child: Text(location),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (String? newValue) {
|
||||
selectedValue.value = newValue;
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../controller/home_controller.dart';
|
||||
|
||||
class DashboardView extends StatelessWidget {
|
||||
const DashboardView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var hCtrl = Get.find<HomeController>();
|
||||
return Center(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
width: 1000,
|
||||
child: Wrap(
|
||||
spacing: 20,
|
||||
runSpacing: 20,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 35.0),
|
||||
child: TextField(
|
||||
controller: hCtrl.dateFromToIsoController.value,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Input From ISO',
|
||||
border: OutlineInputBorder(),
|
||||
hintText: 'Enter Input From ISO',
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 35.0),
|
||||
child: TextField(
|
||||
controller: hCtrl.dateToIsoController.value,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Input To ISO',
|
||||
border: OutlineInputBorder(),
|
||||
hintText: 'Enter Input To ISO',
|
||||
),
|
||||
),
|
||||
),
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.only(right: 35.0),
|
||||
// child: StaticLocationDropdown(
|
||||
// selectedValue: hCtrl.inputSwitchBranches,
|
||||
// ),
|
||||
// ),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
hCtrl.changeView(MainView.dashboard);
|
||||
},
|
||||
child: Image.asset('assets/images/AskiDashboard.png', width: 450),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
hCtrl.changeView(MainView.traun);
|
||||
},
|
||||
child: Image.asset('assets/images/AskiTraun.png', width: 450),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
hCtrl.changeView(MainView.sarleinsbach);
|
||||
},
|
||||
child: Image.asset(
|
||||
'assets/images/AskiSarleinsbach.png',
|
||||
width: 450,
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
hCtrl.changeView(MainView.lannach);
|
||||
},
|
||||
child: Image.asset('assets/images/AskiLannach.png', width: 450),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../../controller/home_controller.dart';
|
||||
import '../comparison_bar_chart.dart';
|
||||
|
||||
class LannachView extends StatelessWidget {
|
||||
const LannachView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var hCtrl = Get.find<HomeController>();
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('PV Lannach'),
|
||||
centerTitle: true,
|
||||
backgroundColor: Colors.blueGrey,
|
||||
foregroundColor: Colors.white,
|
||||
titleTextStyle: const TextStyle(fontSize: 30, color: Colors.white),
|
||||
iconTheme: const IconThemeData(size: 30, color: Colors.white),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () {
|
||||
hCtrl.changeView(MainView.dashboard);
|
||||
},
|
||||
)
|
||||
),
|
||||
body: Obx(
|
||||
() => hCtrl.responseOutputLannachPV.value.dataResult?.values?.isEmpty ?? true
|
||||
? const Center(
|
||||
child: Text(
|
||||
'Keine Daten verfügbar',
|
||||
style: TextStyle(fontSize: 18),
|
||||
),
|
||||
)
|
||||
: ComparisonBarChart(
|
||||
pvData: hCtrl.responseOutputLannachPV.value,
|
||||
importData: hCtrl.responseOutputLannachImport.value,
|
||||
title: 'LannachPV/Import Vergleich',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../controller/home_controller.dart';
|
||||
import '../comparison_bar_chart.dart';
|
||||
|
||||
class SarleinsbachView extends StatelessWidget {
|
||||
const SarleinsbachView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var hCtrl = Get.find<HomeController>();
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('PV Sarleinsbach'),
|
||||
centerTitle: true,
|
||||
backgroundColor: Colors.blueGrey,
|
||||
foregroundColor: Colors.white,
|
||||
titleTextStyle: const TextStyle(fontSize: 30, color: Colors.white),
|
||||
iconTheme: const IconThemeData(size: 30, color: Colors.white),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () {
|
||||
hCtrl.changeView(MainView.dashboard);
|
||||
},
|
||||
)
|
||||
),
|
||||
body: Obx(
|
||||
() => hCtrl.responseOutputSarleinsbachPV.value.dataResult?.values?.isEmpty ?? true
|
||||
? const Center(
|
||||
child: Text(
|
||||
'Keine Daten verfügbar',
|
||||
style: TextStyle(fontSize: 18),
|
||||
),
|
||||
)
|
||||
: ComparisonBarChart(
|
||||
pvData: hCtrl.responseOutputSarleinsbachPV.value,
|
||||
importData: hCtrl.responseOutputSarleinsbachImport.value,
|
||||
title: 'SarleinsbachPV/Import Vergleich',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../controller/home_controller.dart';
|
||||
|
||||
class SettingsView extends StatelessWidget {
|
||||
const SettingsView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var hCtrl = Get.find<HomeController>();
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('System Settings'),
|
||||
centerTitle: true,
|
||||
backgroundColor: Colors.blueGrey,
|
||||
foregroundColor: Colors.white,
|
||||
titleTextStyle: const TextStyle(fontSize: 30, color: Colors.white),
|
||||
iconTheme: const IconThemeData(size: 30, color: Colors.white),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () {
|
||||
hCtrl.changeView(MainView.dashboard);
|
||||
},
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.save),
|
||||
onPressed: () {
|
||||
// Save the login URL to the controller
|
||||
hCtrl.saveSettings();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(18.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 10),
|
||||
Text(
|
||||
"Please enter User and Password for Web Methodes",
|
||||
style: TextStyle(fontSize: 18),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
TextField(
|
||||
controller: hCtrl.userWebMethodesController.value,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Input User',
|
||||
border: OutlineInputBorder(),
|
||||
hintText: 'Enter Admin User',
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
TextField(
|
||||
controller: hCtrl.passwordWebMethodesController.value,
|
||||
obscureText: true,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Input Password',
|
||||
border: OutlineInputBorder(),
|
||||
hintText: 'Enter Admin Password',
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Text(
|
||||
"Please enter the URLs for WebMethodes PV data Url",
|
||||
style: TextStyle(fontSize: 18),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
TextField(
|
||||
controller: hCtrl.powerUrlController.value,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Power URL',
|
||||
border: OutlineInputBorder(),
|
||||
hintText: 'Enter ASKI Power URL',
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../../controller/home_controller.dart';
|
||||
import '../comparison_bar_chart.dart';
|
||||
|
||||
class TraunView extends StatelessWidget {
|
||||
const TraunView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var hCtrl = Get.find<HomeController>();
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('PV Traun'),
|
||||
centerTitle: true,
|
||||
backgroundColor: Colors.blueGrey,
|
||||
foregroundColor: Colors.white,
|
||||
titleTextStyle: const TextStyle(fontSize: 30, color: Colors.white),
|
||||
iconTheme: const IconThemeData(size: 30, color: Colors.white),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () {
|
||||
hCtrl.changeView(MainView.dashboard);
|
||||
},
|
||||
)
|
||||
),
|
||||
body: Obx(
|
||||
() => hCtrl.responseOutputTraunPV.value.dataResult?.values?.isEmpty ?? true
|
||||
? const Center(
|
||||
child: Text(
|
||||
'Keine Daten verfügbar',
|
||||
style: TextStyle(fontSize: 18),
|
||||
),
|
||||
)
|
||||
: ComparisonBarChart(
|
||||
pvData: hCtrl.responseOutputTraunPV.value,
|
||||
importData: hCtrl.responseOutputTraunImport.value,
|
||||
title: 'TraunPV/Import Vergleich',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
jni
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import device_info_plus
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||
}
|
||||
|
||||
+294
-1
@@ -1,6 +1,14 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.7.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -33,6 +41,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
code_assets:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: code_assets
|
||||
sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -41,6 +57,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.19.1"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.7"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -49,6 +73,30 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.9"
|
||||
device_info_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: device_info_plus
|
||||
sha256: a7fd703482b391a87d60b6061d04dfdeab07826b96f9abd8f5ed98068acc0074
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.1.2"
|
||||
device_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: device_info_plus_platform_interface
|
||||
sha256: e1ea89119e34903dca74b883d0dd78eb762814f97fb6c76f35e9ff74d261a18f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.3"
|
||||
equatable:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: equatable
|
||||
sha256: "3bce007a596ff8b3119c45d68aaef631272537c03d30e5d4534dd24bf4c5eaa2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -57,6 +105,30 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.3"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
fl_chart:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: fl_chart
|
||||
sha256: d0f0d49112f2f4b192481c16d05b6418bd7820e021e265a3c22db98acf7ed7fb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.68.0"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@@ -75,6 +147,75 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
get:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: get
|
||||
sha256: "5ed34a7925b85336e15d472cc4cfe7d9ebf4ab8e8b9f688585bf6b50f4c3d79a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.7.3"
|
||||
get_storage:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: get_storage
|
||||
sha256: "39db1fffe779d0c22b3a744376e86febe4ade43bf65e06eab5af707dc84185a2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
hooks:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: hooks
|
||||
sha256: "9a62a50b50b769a737bc0a8ff381f333529df3ab746b2f6b02e83760231455ba"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
http:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: http
|
||||
sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.6.0"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.2"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: intl
|
||||
sha256: "1ca20c894b1717686a2319b8548763d812bc0aabdac580420a44c5178c57a867"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.20.3"
|
||||
jni:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: jni
|
||||
sha256: c2230682d5bc2362c1c9e8d3c7f406d9cbba23ab3f2e203a025dd47e0fb2e68f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
jni_flutter:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: jni_flutter
|
||||
sha256: "8b59e590786050b1cd866677dddaf76b1ade5e7bc751abe04b86e84d379d3ba6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -107,6 +248,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.0"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logging
|
||||
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -131,6 +280,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.18.0"
|
||||
objective_c:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: objective_c
|
||||
sha256: "6cb691c686fa2838c6deb34980d426145c2a5d537491cb83d463c33cdbc726ed"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.4.1"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_config
|
||||
sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -139,6 +304,86 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
path_provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: a7f4874f987173da295a61c181b8ee71dab59b332a486b391babf26a1b884825
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.6"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: "69cbd515a62b94d32a7944f086b2f82b4ac40a1d45bebfc00813a430ab2dabcd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.6.0"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
sha256: "58c2005f147315b11e9b4a7bc889cd5203e250cba8e3f012dae259b4972b5c16"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.2"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
sha256: "484838772624c3a4b94f1e44a3e19897fee738f2d5c4ce448443b0417f7c9dda"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.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"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pub_semver
|
||||
sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
record_use:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: record_use
|
||||
sha256: "2551bd8eecfe95d14ae75f6021ad0248be5c27f138c2ec12fcb52b500b3ba1ed"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.0"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@@ -192,6 +437,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.11"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -208,6 +461,46 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "15.2.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.15.0"
|
||||
win32_registry:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32_registry
|
||||
sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.5"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
sdks:
|
||||
dart: ">=3.12.2 <4.0.0"
|
||||
flutter: ">=3.18.0-18.0.pre.54"
|
||||
flutter: ">=3.38.4"
|
||||
|
||||
+13
-70
@@ -1,89 +1,32 @@
|
||||
name: flutter_test_services
|
||||
description: "A new Flutter project."
|
||||
# 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.
|
||||
publish_to: "none"
|
||||
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: ^3.12.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:
|
||||
cupertino_icons: ^1.0.8
|
||||
fl_chart: ^0.68.0
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^1.0.8
|
||||
get: ^4.7.3
|
||||
get_storage: ^2.1.1
|
||||
http: ^1.6.0
|
||||
intl: ^0.20.3
|
||||
device_info_plus: ^10.1.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_lints: ^6.0.0
|
||||
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: ^6.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
|
||||
assets:
|
||||
- assets/images/
|
||||
- assets/icons/
|
||||
|
||||
@@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
jni
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
||||
@@ -26,8 +26,8 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
||||
|
||||
FlutterWindow window(project);
|
||||
Win32Window::Point origin(10, 10);
|
||||
Win32Window::Size size(1280, 720);
|
||||
if (!window.Create(L"flutter_test_services", origin, size)) {
|
||||
Win32Window::Size size(1280, 986);
|
||||
if (!window.Create(L"IFN ASKI Inside", origin, size)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
window.SetQuitOnClose(true);
|
||||
|
||||
Reference in New Issue
Block a user