first commit

This commit is contained in:
atseirjo
2026-01-23 07:33:20 +01:00
commit aeca07a5a3
31 changed files with 1831 additions and 0 deletions

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-dependencies
.pub-cache/
.pub/
/build/
/coverage/
# 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

30
.metadata Normal file
View File

@@ -0,0 +1,30 @@
# 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: "3b62efc2a3da49882f43c372e0bc53daef7295a6"
channel: "stable"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6
base_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6
- platform: web
create_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6
base_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6
# 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'

16
README.md Normal file
View File

@@ -0,0 +1,16 @@
# flutter_tank_web_app
A new Flutter project.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.

31
analysis_options.yaml Normal file
View File

@@ -0,0 +1,31 @@
# 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.
analyzer:
errors:
avoid_print: ignore
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

BIN
assets/images/guru.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
assets/images/guru01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@@ -0,0 +1,7 @@
class Environment {
static const String appwritePublicEndpoint = 'https://appwrite.joshihomeserver.ipv64.net/v1';
static const String appwriteProjectId = '6894f2b0001f127bab72';
static const String appwriteProjectName = 'Flutter Projects';
static const String appwriteRealtimeCollectionId = '68a22f520035a95d6666';
static const String appwriteDatabaseId = '68a22ef90021b90f0f43';
}

View File

@@ -0,0 +1,85 @@
import 'package:get/get.dart';
import '../models/tank_model.dart';
import '../services/appwrite_service.dart';
class HomeController extends GetxController {
final isLoading = false.obs;
final listTankModel = <TankModel>[].obs;
final appwriteService = AppwriteService();
@override
void onInit() {
_loadListDocument();
super.onInit();
}
@override
void onReady() {}
@override
void onClose() {}
Future<void> _loadListDocument() async {
isLoading.value = true;
if(listTankModel.isNotEmpty){
listTankModel.clear();
}
var dateYear = DateTime.now().year;
var userId = await appwriteService.getCurrentUserId();
if (userId == null) {
//User nicht eingeloggt, evtl. zur Login-Seite navigieren
update();
return;
}
var resultList = await appwriteService.getDocumentsFromCollection(userId);
if (resultList.isEmpty) {
//Dokumente erfolgreich geladen, hier können Sie die Liste verarbeiten
print('Dokumente wurden nicht geladen: ${resultList.length}');
} else {
for (var doc in resultList) {
var tankModel = TankModel.fromMap(doc.data);
listTankModel.add(tankModel);
}
if (listTankModel.isNotEmpty) {
var sortList = listTankModel.where((tank) {
var year = (DateTime.tryParse(tank.szDate)!).year;
return year == dateYear;
}).toList();
listTankModel.clear();
listTankModel.addAll(sortList);
listTankModel.sort((a, b) {
var dateA = DateTime.tryParse(a.szDate)!;
var dateB = DateTime.tryParse(b.szDate)!;
return dateB.compareTo(dateA);
});
for (var tank in listTankModel) {
print(
'SortTankModel: ${tank.szDate} - ${tank.szLiters}L - ${tank.szPricePerLiter}€/L - Total: ${tank.szPriceTotal}',
);
}
}
}
isLoading.value = false;
update();
}
Future<void> logout() async {
var logoutSuccess = await appwriteService.logout();
if (logoutSuccess) {
Get.snackbar(
'Logout erfolgreich',
'Sie wurden abgemeldet.',
snackPosition: SnackPosition.BOTTOM,
);
Get.offAllNamed('/login-page');
} else {
Get.snackbar(
'Logout fehlgeschlagen',
'Bitte versuchen Sie es erneut.',
snackPosition: SnackPosition.BOTTOM,
);
}
}
}

View File

@@ -0,0 +1,46 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../pages/home_view.dart';
import '../pages/signin_view.dart';
import '../services/appwrite_service.dart';
class LoginController extends GetxController {
final emailController = TextEditingController();
final passwordController = TextEditingController();
final appwriteService = AppwriteService();
@override
void onReady() {}
@override
void onClose() {
emailController.dispose();
passwordController.dispose();
}
void login() async {
var email = emailController.text;
var password = passwordController.text;
// Hier können Sie die Login-Logik implementieren
print('Login mit E-Mail: $email, Passwort: $password');
var loginSuccess = await appwriteService.login(email, password);
if (loginSuccess) {
Get.snackbar(
'Login erfolgreich',
'Willkommen zurück!',
snackPosition: SnackPosition.BOTTOM,
);
Get.offAndToNamed(HomePage.namedRoute);
} else {
Get.snackbar(
'Login fehlgeschlagen',
'Bitte überprüfen Sie Ihre E-Mail und Ihr Passwort und versuchen Sie es erneut.',
snackPosition: SnackPosition.BOTTOM,
);
}
}
void goToSignInPage() {
Get.offAndToNamed(SigninPage.namedRoute);
}
}

View File

@@ -0,0 +1,87 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../pages/home_view.dart';
import '../pages/login_view.dart';
import '../services/appwrite_service.dart';
class SigninController extends GetxController {
final userNameController = TextEditingController();
final emailController = TextEditingController();
final passwordController = TextEditingController();
final appwriteService = AppwriteService();
@override
void onReady() {}
@override
void onClose() {
userNameController.dispose();
emailController.dispose();
passwordController.dispose();
}
void register() async {
//Eingaben überprüfen
if (!_checkInputs()) return;
//Registrierungslogik
var userName = userNameController.text;
var email = emailController.text;
var password = passwordController.text;
// Testausgabe
print(
'Registrieren mit Benutzername: $userName, E-Mail: $email, Passwort: $password',
);
//appwrite Registrierung und login Logik hier einfügen
var registrationSuccess = await appwriteService.register(
userName,
email,
password,
);
//Nach erfolgreicher Registrierung Meldung und zur Startseite navigieren
if (registrationSuccess) {
Get.snackbar(
'Registrierung erfolgreich, sie werden weitergeleitet',
'Willkommen, $userName!',
snackPosition: SnackPosition.BOTTOM,
);
Get.offAndToNamed(HomePage.namedRoute);
} else {
Get.snackbar(
'Registrierung fehlgeschlagen',
'Bitte überprüfen Sie Ihre Eingaben und versuchen Sie es erneut.',
snackPosition: SnackPosition.BOTTOM,
);
}
}
void goToLoginPage() {
Get.offAndToNamed(LoginPage.namedRoute);
}
bool _checkInputs() {
var isOk = false;
if (userNameController.text.isEmpty ||
emailController.text.isEmpty ||
passwordController.text.isEmpty) {
Get.snackbar(
'Fehler',
'Bitte alle Felder ausfüllen',
snackPosition: SnackPosition.BOTTOM,
);
isOk = false;
} else {
isOk = true;
}
if (passwordController.text.length < 6) {
Get.snackbar(
'Fehler',
'Passwort muss mindestens 6 Zeichen lang sein',
snackPosition: SnackPosition.BOTTOM,
);
isOk = false;
} else {
isOk = true;
}
return isOk;
}
}

10
lib/helper/helper.dart Normal file
View File

@@ -0,0 +1,10 @@
import 'package:intl/intl.dart';
/// Retrieves the current date in the format "yyyy-MM-dd".
///
/// @return [String] A formatted date.
String getCurrentDate(DateTime date) {
return DateFormat("yyyy-MM-dd").format(date);
}

View File

@@ -0,0 +1,19 @@
import 'package:get/get.dart';
import '../controller/home_controller.dart';
import '../controller/login_controller.dart';
import '../controller/signin_controller.dart';
class SampleBindings extends Bindings {
@override
void dependencies() {
// Define your dependencies here no permanent Binding
Get.lazyPut<LoginController>(() => LoginController());
Get.lazyPut<SigninController>(() => SigninController());
Get.lazyPut<HomeController>(() => HomeController());
}
}

View File

@@ -0,0 +1,27 @@
import 'package:get/get.dart';
import 'sample_bindings.dart';
import '../pages/home_view.dart';
import '../pages/signin_view.dart';
import '../pages/login_view.dart';
class SampleRouts {
static final sampleBindings = SampleBindings();
static List<GetPage<dynamic>> samplePages = [
GetPage(
name: LoginPage.namedRoute,
page: () => const LoginPage(),
binding: sampleBindings,
),
GetPage(
name: SigninPage.namedRoute,
page: () => const SigninPage(),
binding: sampleBindings,
),
GetPage(
name: HomePage.namedRoute,
page: () => const HomePage(),
binding: sampleBindings,
),
];
}

28
lib/main.dart Normal file
View File

@@ -0,0 +1,28 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'helper/sample_bindings.dart';
import 'helper/sample_routes.dart';
import 'pages/login_view.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(colorScheme: .fromSeed(seedColor: Colors.deepPurple)),
initialBinding: SampleBindings(),
initialRoute: LoginPage.namedRoute,
getPages: SampleRouts.samplePages,
);
}
}

View File

@@ -0,0 +1,82 @@
import 'dart:convert';
class TankModel {
final String szDocumentId;
final String szUserId;
final String szDate;
final String szOdometer;
final String szLiters;
final String szPricePerLiter;
final String szLocation;
final String szPriceTotal;
TankModel({
required this.szDocumentId,
required this.szUserId,
required this.szDate,
required this.szOdometer,
required this.szLiters,
required this.szPricePerLiter,
required this.szLocation,
required this.szPriceTotal,
});
TankModel copyWith({
String? szDocumentId,
String? szUserId,
String? szDate,
String? szOdometer,
String? szLiters,
String? szPricePerLiter,
String? szLocation,
String? szPriceTotal,
}) {
return TankModel(
szDocumentId: szDocumentId ?? this.szDocumentId,
szUserId: szUserId ?? this.szUserId,
szDate: szDate ?? this.szDate,
szOdometer: szOdometer ?? this.szOdometer,
szLiters: szLiters ?? this.szLiters,
szPricePerLiter: szPricePerLiter ?? this.szPricePerLiter,
szLocation: szLocation ?? this.szLocation,
szPriceTotal: szPriceTotal ?? this.szPriceTotal,
);
}
Map<String, dynamic> toMap() {
final result = <String, dynamic>{};
result.addAll({'\$id': szDocumentId});
result.addAll({'userId': szUserId});
result.addAll({'date': szDate});
result.addAll({'odometer': szOdometer});
result.addAll({'liters': szLiters});
result.addAll({'pricePerLiter': szPricePerLiter});
result.addAll({'location': szLocation});
result.addAll({'priceTotal': szPriceTotal});
return result;
}
factory TankModel.fromMap(Map<String, dynamic> map) {
return TankModel(
szDocumentId: map['\$id'] ?? '',
szUserId: map['userId'] ?? '',
szDate: map['date'] ?? '',
szOdometer: map['odometer'] ?? '',
szLiters: map['liters'] ?? '',
szPricePerLiter: map['pricePerLiter'] ?? '',
szLocation: map['location'] ?? '',
szPriceTotal: (double.parse(map['liters']?.toString() ?? '0') * double.parse(map['pricePerLiter']?.toString() ?? '0')).toStringAsFixed(2),
);
}
String toJson() => json.encode(toMap());
factory TankModel.fromJson(String source) => TankModel.fromMap(json.decode(source));
@override
String toString() {
return 'TankModel(szDocumentId: $szDocumentId, szUserId: $szUserId, szDate: $szDate, szOdometer: $szOdometer, szLiters: $szLiters, szPricePerLiter: $szPricePerLiter, szLocation: $szLocation, szPriceTotal: $szPriceTotal)';
}
}

56
lib/pages/home_view.dart Normal file
View File

@@ -0,0 +1,56 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controller/home_controller.dart';
class HomePage extends GetView<HomeController> {
static const String namedRoute = '/home-page';
const HomePage({super.key});
@override
Widget build(BuildContext context) {
var homCtrl = controller;
return PopScope(
canPop: false,
child: SafeArea(
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.blueGrey,
foregroundColor: Colors.white,
title: const Text('Tank List'),
centerTitle: true,
actions: [
IconButton(
icon: const Icon(Icons.refresh),
onPressed: () {
controller.onInit();
},
),
IconButton(
onPressed: () => homCtrl.logout(),
icon: Icon(Icons.logout),
),
],
),
body: Obx(
() => homCtrl.isLoading.value == false
? ListView.builder(
itemBuilder: (context, index) {
var tank = homCtrl.listTankModel[index];
return ListTile(
title: Text(
'${tank.szDate} - ${tank.szLiters}L - ${tank.szPricePerLiter}€/L',
),
subtitle: Text(
'Total: ${tank.szPriceTotal}€ - Odometer: ${tank.szOdometer}km',
),
);
},
itemCount: homCtrl.listTankModel.length,
)
: Center(child: CircularProgressIndicator()),
),
),
),
);
}
}

36
lib/pages/login_view.dart Normal file
View File

@@ -0,0 +1,36 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controller/login_controller.dart';
import '../widgets/my_login_widget.dart';
class LoginPage extends GetView<LoginController> {
static const String namedRoute = '/login-page';
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
var logCtrl = controller;
var displayWidth = MediaQuery.of(context).size.width;
var displayHeight = MediaQuery.of(context).size.height;
return SafeArea(
child: Scaffold(
body: Container(
height: displayHeight,
width: displayWidth,
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 130.0,
),
color: Colors.blue.shade100,
child: SingleChildScrollView(
child: MyLoginWidget(
onButtonPressed: () => logCtrl.login(),
signInOnTab: () => logCtrl.goToSignInPage(),
logCtrl: logCtrl,
),
),
),
),
);
}
}

View File

@@ -0,0 +1,36 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controller/signin_controller.dart';
import '../widgets/my_signin_widget.dart';
class SigninPage extends GetView<SigninController> {
static const String namedRoute = '/signin-page';
const SigninPage({super.key});
@override
Widget build(BuildContext context) {
var sigCtrl = controller;
var displayWidth = MediaQuery.of(context).size.width;
var displayHeight = MediaQuery.of(context).size.height;
return SafeArea(
child: Scaffold(
body: Container(
height: displayHeight,
width: displayWidth,
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 100.0,
),
color: Colors.blue.shade100,
child: SingleChildScrollView(
child: MySigninWidget(
signCtrl: sigCtrl,
onButtonPressed: () => sigCtrl.register(),
logInOnTab: () => sigCtrl.goToLoginPage(),
),
),
),
),
);
}
}

View File

@@ -0,0 +1,168 @@
import 'package:appwrite/models.dart';
import 'package:appwrite/appwrite.dart';
import '../config/environment.dart';
class AppwriteService {
static final String endpoint = Environment.appwritePublicEndpoint;
static final String projectId = Environment.appwriteProjectId;
static final String projectName = Environment.appwriteProjectName;
static final String realtimeCollectionId =
Environment.appwriteRealtimeCollectionId;
static final String databaseId = Environment.appwriteDatabaseId;
final Client _client = Client().setProject(projectId).setEndpoint(endpoint);
// ignore: unused_field
late final Account _account;
// ignore: unused_field
late final Databases _databases;
AppwriteService._internal() {
_account = Account(_client);
_databases = Databases(_client);
}
static final AppwriteService _instance = AppwriteService._internal();
/// Singleton instance getter
factory AppwriteService() => _instance;
// register new user with userName, e-Mail and password
Future<bool> register(String userName, String email, String password) async {
try {
final user = await _account.create(
userId: ID.unique(),
email: email,
password: password,
name: userName,
);
print('Registrierung erfolgreich: ${user.$id}');
return true;
} catch (e) {
print('Registrierung fehlgeschlagen: $e');
return false;
}
}
// login with e-Mail and password
Future<bool> login(String email, String password) async {
await logout();
try {
final session = await _account.createEmailPasswordSession(
email: email,
password: password,
);
print('Login erfolgreich: ${session.$id}');
return true;
} catch (e) {
print('Login fehlgeschlagen: $e');
return false;
}
}
// logout current user
Future<bool> logout() async {
try {
await _account.deleteSession(sessionId: 'current');
print('Logout erfolgreich');
return true;
} catch (e) {
print('Logout fehlgeschlagen: $e');
return false;
}
}
//Get current user ID
Future<String?> getCurrentUserId() async {
try {
final user = await _account.get();
return user.$id;
} catch (e) {
print('Fehler beim Abrufen der Benutzer-ID: $e');
return null;
}
}
// Get List<Document> from Realtime Collection
Future<List<Document>> getDocumentsFromCollection(String userId) async {
try {
final documents = await _databases.listDocuments(
databaseId: databaseId,
collectionId: realtimeCollectionId,
queries: [Query.equal('userId', userId), Query.orderDesc('date')],
);
return documents.documents;
} catch (e) {
print('Fehler beim Abrufen der Dokumente: $e');
return [];
}
}
// Get Document per Id from Realtime Collection
Future<Document?> getDocumentById(String documentId) async {
try {
final document = await _databases.getDocument(
databaseId: databaseId,
collectionId: realtimeCollectionId,
documentId: documentId,
);
return document;
} catch (e) {
print('Fehler beim Abrufen des Dokuments: $e');
return null;
}
}
// Save a new document to Realtime Collection
Future<bool> createDocumentInCollection(Map<String, dynamic> data) async {
try {
await _databases.createDocument(
databaseId: databaseId,
collectionId: realtimeCollectionId,
documentId: ID.unique(),
data: data,
);
print('Dokument erfolgreich erstellt');
return true;
} catch (e) {
print('Fehler beim Erstellen des Dokuments: $e');
return false;
}
}
// Update an existing document in Realtime Collection
Future<bool> updateDocumentInCollection(
String documentId,
Map<String, dynamic> data,
) async {
try {
await _databases.updateDocument(
databaseId: databaseId,
collectionId: realtimeCollectionId,
documentId: documentId,
data: data,
);
print('Dokument erfolgreich aktualisiert');
return true;
} catch (e) {
print('Fehler beim Aktualisieren des Dokuments: $e');
return false;
}
}
// Delete a document from Realtime Collection
Future<bool> deleteDocumentFromCollection(String documentId) async {
try {
await _databases.deleteDocument(
databaseId: databaseId,
collectionId: realtimeCollectionId,
documentId: documentId,
);
print('Dokument erfolgreich gelöscht');
return true;
} catch (e) {
print('Fehler beim Löschen des Dokuments: $e');
return false;
}
}
}

View File

@@ -0,0 +1,134 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart' show GoogleFonts;
import '../controller/login_controller.dart';
class MyLoginWidget extends StatelessWidget {
final void Function()? onButtonPressed;
final void Function()? signInOnTab;
final LoginController logCtrl;
const MyLoginWidget({
super.key,
this.onButtonPressed,
this.signInOnTab,
required this.logCtrl,
});
@override
Widget build(BuildContext context) {
final googleFont = GoogleFonts.righteous().fontFamily;
return Column(
children: [
Stack(
children: [
// Umriss (Outline)
Text(
"Login Page",
style: TextStyle(
fontSize: 44,
fontFamily: googleFont,
fontStyle: FontStyle.normal,
letterSpacing: 5.0,
foreground: Paint()
..style = PaintingStyle.stroke
..strokeWidth = 5
..color = Colors.blue.shade900,
),
),
// Füllung
Text(
"Login Page",
style: TextStyle(
fontSize: 44,
fontFamily: googleFont,
fontStyle: FontStyle.normal,
color: Colors.orange.shade300,
letterSpacing: 5.0,
),
),
],
),
SizedBox(height: 20),
Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.orange.shade400, width: 8),
borderRadius: BorderRadius.circular(30),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(18),
child: Image.asset(
'assets/images/guru.png',
width: 400,
height: 400,
),
),
),
SizedBox(height: 20),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 50.0),
child: TextField(
controller: logCtrl.emailController,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'E-Mail',
),
),
),
SizedBox(height: 20),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 50.0),
child: TextField(
obscureText: true,
controller: logCtrl.passwordController,
keyboardType: TextInputType.visiblePassword,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password',
),
),
),
SizedBox(height: 30),
ElevatedButton(
style: ButtonStyle(
backgroundColor: WidgetStatePropertyAll<Color>(
Colors.orange.shade500,
),
foregroundColor: WidgetStatePropertyAll<Color>(
Colors.blue.shade900,
),
minimumSize: WidgetStatePropertyAll<Size>(Size(430, 60)),
),
onPressed: onButtonPressed,
child: Text(
'Login',
style: TextStyle(fontSize: 34, fontFamily: googleFont),
),
),
SizedBox(height: 10),
RichText(
text: TextSpan(
style: TextStyle(fontSize: 16, color: Colors.black),
children: [
TextSpan(text: 'Zum registrieren '),
WidgetSpan(
child: GestureDetector(
onTap: signInOnTab,
child: Text(
'Sign in',
style: TextStyle(
fontSize: 16,
color: Colors.blue.shade700,
decoration: TextDecoration.underline,
),
),
),
),
TextSpan(text: ' clicken!!'),
],
),
),
],
);
}
}

View File

@@ -0,0 +1,146 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart' show GoogleFonts;
import '../controller/signin_controller.dart';
class MySigninWidget extends StatelessWidget {
final void Function()? onButtonPressed;
final void Function()? logInOnTab;
final SigninController signCtrl;
const MySigninWidget({
super.key,
this.onButtonPressed,
this.logInOnTab,
required this.signCtrl,
});
@override
Widget build(BuildContext context) {
final googleFont = GoogleFonts.righteous().fontFamily;
return Column(
children: [
Stack(
children: [
// Umriss (Outline)
Text(
"Signin Page",
style: TextStyle(
fontSize: 44,
fontFamily: googleFont,
fontStyle: FontStyle.normal,
letterSpacing: 5.0,
foreground: Paint()
..style = PaintingStyle.stroke
..strokeWidth = 5
..color = Colors.blue.shade900,
),
),
// Füllung
Text(
"Signin Page",
style: TextStyle(
fontSize: 44,
fontFamily: googleFont,
fontStyle: FontStyle.normal,
color: Colors.orange.shade300,
letterSpacing: 5.0,
),
),
],
),
SizedBox(height: 20),
Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.orange.shade400, width: 8),
borderRadius: BorderRadius.circular(30),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(18),
child: Image.asset(
'assets/images/guru01.png',
width: 400,
height: 400,
),
),
),
SizedBox(height: 20),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 50.0),
child: TextField(
controller: signCtrl.userNameController,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Username',
),
),
),
SizedBox(height: 20),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 50.0),
child: TextField(
controller: signCtrl.emailController,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Email',
),
),
),
SizedBox(height: 20),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 50.0),
child: TextField(
obscureText: true,
controller: signCtrl.passwordController,
keyboardType: TextInputType.visiblePassword,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password',
),
),
),
SizedBox(height: 30),
ElevatedButton(
style: ButtonStyle(
backgroundColor: WidgetStatePropertyAll<Color>(
Colors.orange.shade500,
),
foregroundColor: WidgetStatePropertyAll<Color>(
Colors.blue.shade900,
),
minimumSize: WidgetStatePropertyAll<Size>(Size(430, 60)),
),
onPressed: onButtonPressed,
child: Text(
'Register',
style: TextStyle(fontSize: 34, fontFamily: googleFont),
),
),
SizedBox(height: 10),
RichText(
text: TextSpan(
style: TextStyle(fontSize: 16, color: Colors.black),
children: [
TextSpan(text: 'Zum login '),
WidgetSpan(
child: GestureDetector(
onTap: logInOnTab,
child: Text(
'Log in',
style: TextStyle(
fontSize: 16,
color: Colors.blue.shade700,
decoration: TextDecoration.underline,
),
),
),
),
TextSpan(text: ' clicken!!'),
],
),
),
],
);
}
}

610
pubspec.lock Normal file
View File

@@ -0,0 +1,610 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
appwrite:
dependency: "direct main"
description:
name: appwrite
sha256: "3e1f618c8f75bafa49ef7b1b445f64c53cf4620a195443f4d119bbc95a666d0a"
url: "https://pub.dev"
source: hosted
version: "14.0.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"
clock:
dependency: transitive
description:
name: clock
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
url: "https://pub.dev"
source: hosted
version: "1.1.2"
code_assets:
dependency: transitive
description:
name: code_assets
sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
collection:
dependency: transitive
description:
name: collection
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
url: "https://pub.dev"
source: hosted
version: "1.19.1"
cookie_jar:
dependency: transitive
description:
name: cookie_jar
sha256: a6ac027d3ed6ed756bfce8f3ff60cb479e266f3b0fdabd6242b804b6765e52de
url: "https://pub.dev"
source: hosted
version: "4.0.8"
crypto:
dependency: transitive
description:
name: crypto
sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf
url: "https://pub.dev"
source: hosted
version: "3.0.7"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
url: "https://pub.dev"
source: hosted
version: "1.0.8"
device_info_plus:
dependency: transitive
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"
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: d07d37192dbf97461359c1518788f203b0c9102cfd2c35a716b823741219542c
url: "https://pub.dev"
source: hosted
version: "2.1.5"
file:
dependency: transitive
description:
name: file
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
url: "https://pub.dev"
source: hosted
version: "7.0.1"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1"
url: "https://pub.dev"
source: hosted
version: "6.0.0"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
flutter_web_auth_2:
dependency: transitive
description:
name: flutter_web_auth_2
sha256: "4d3d2fd3d26bf1a26b3beafd4b4b899c0ffe10dc99af25abc58ffe24e991133c"
url: "https://pub.dev"
source: hosted
version: "3.1.2"
flutter_web_auth_2_platform_interface:
dependency: transitive
description:
name: flutter_web_auth_2_platform_interface
sha256: e8669e262005a8354389ba2971f0fc1c36188481234ff50d013aaf993f30f739
url: "https://pub.dev"
source: hosted
version: "3.1.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"
glob:
dependency: transitive
description:
name: glob
sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de
url: "https://pub.dev"
source: hosted
version: "2.1.3"
google_fonts:
dependency: "direct main"
description:
name: google_fonts
sha256: "6996212014b996eaa17074e02b1b925b212f5e053832d9048970dc27255a8fb3"
url: "https://pub.dev"
source: hosted
version: "7.1.0"
hooks:
dependency: transitive
description:
name: hooks
sha256: "5d309c86e7ce34cd8e37aa71cb30cb652d3829b900ab145e4d9da564b31d59f7"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
http:
dependency: transitive
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: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5"
url: "https://pub.dev"
source: hosted
version: "0.20.2"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
url: "https://pub.dev"
source: hosted
version: "11.0.2"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
url: "https://pub.dev"
source: hosted
version: "3.0.10"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
url: "https://pub.dev"
source: hosted
version: "3.0.2"
lints:
dependency: transitive
description:
name: lints
sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0
url: "https://pub.dev"
source: hosted
version: "6.0.0"
logging:
dependency: transitive
description:
name: logging
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
url: "https://pub.dev"
source: hosted
version: "1.3.0"
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: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
url: "https://pub.dev"
source: hosted
version: "1.17.0"
native_toolchain_c:
dependency: transitive
description:
name: native_toolchain_c
sha256: "89e83885ba09da5fdf2cdacc8002a712ca238c28b7f717910b34bcd27b0d03ac"
url: "https://pub.dev"
source: hosted
version: "0.17.4"
objective_c:
dependency: transitive
description:
name: objective_c
sha256: "9922a1ad59ac5afb154cc948aa6ded01987a75003651d0a2866afc23f4da624e"
url: "https://pub.dev"
source: hosted
version: "9.2.3"
package_info_plus:
dependency: transitive
description:
name: package_info_plus
sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968"
url: "https://pub.dev"
source: hosted
version: "8.3.1"
package_info_plus_platform_interface:
dependency: transitive
description:
name: package_info_plus_platform_interface
sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086"
url: "https://pub.dev"
source: hosted
version: "3.2.1"
path:
dependency: transitive
description:
name: path
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
url: "https://pub.dev"
source: hosted
version: "1.9.1"
path_provider:
dependency: transitive
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: f2c65e21139ce2c3dad46922be8272bb5963516045659e71bb16e151c93b580e
url: "https://pub.dev"
source: hosted
version: "2.2.22"
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: 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"
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"
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: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
url: "https://pub.dev"
source: hosted
version: "0.7.7"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
url: "https://pub.dev"
source: hosted
version: "1.4.0"
universal_io:
dependency: transitive
description:
name: universal_io
sha256: f63cbc48103236abf48e345e07a03ce5757ea86285ed313a6a032596ed9301e2
url: "https://pub.dev"
source: hosted
version: "2.3.1"
url_launcher:
dependency: transitive
description:
name: url_launcher
sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8
url: "https://pub.dev"
source: hosted
version: "6.3.2"
url_launcher_android:
dependency: transitive
description:
name: url_launcher_android
sha256: "767344bf3063897b5cf0db830e94f904528e6dd50a6dfaf839f0abf509009611"
url: "https://pub.dev"
source: hosted
version: "6.3.28"
url_launcher_ios:
dependency: transitive
description:
name: url_launcher_ios
sha256: cfde38aa257dae62ffe79c87fab20165dfdf6988c1d31b58ebf59b9106062aad
url: "https://pub.dev"
source: hosted
version: "6.3.6"
url_launcher_linux:
dependency: transitive
description:
name: url_launcher_linux
sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a
url: "https://pub.dev"
source: hosted
version: "3.2.2"
url_launcher_macos:
dependency: transitive
description:
name: url_launcher_macos
sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18"
url: "https://pub.dev"
source: hosted
version: "3.2.5"
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: d0412fcf4c6b31ecfdb7762359b7206ffba3bbffd396c6d9f9c4616ece476c1f
url: "https://pub.dev"
source: hosted
version: "2.4.2"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f"
url: "https://pub.dev"
source: hosted
version: "3.1.5"
vector_math:
dependency: transitive
description:
name: vector_math
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
url: "https://pub.dev"
source: hosted
version: "2.2.0"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60"
url: "https://pub.dev"
source: hosted
version: "15.0.2"
web:
dependency: transitive
description:
name: web
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
url: "https://pub.dev"
source: hosted
version: "1.1.1"
web_socket:
dependency: transitive
description:
name: web_socket
sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c"
url: "https://pub.dev"
source: hosted
version: "1.0.1"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8
url: "https://pub.dev"
source: hosted
version: "3.0.3"
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"
window_to_front:
dependency: transitive
description:
name: window_to_front
sha256: "7aef379752b7190c10479e12b5fd7c0b9d92adc96817d9e96c59937929512aee"
url: "https://pub.dev"
source: hosted
version: "0.0.3"
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.10.7 <4.0.0"
flutter: ">=3.38.4"

29
pubspec.yaml Normal file
View File

@@ -0,0 +1,29 @@
name: flutter_tank_web_app
description: "A new Flutter project."
publish_to: "none"
version: 1.0.0+1
environment:
sdk: ^3.10.7
dependencies:
cupertino_icons: ^1.0.8
flutter:
sdk: flutter
get: ^4.7.3
google_fonts: ^7.1.0
intl: ^0.20.2
appwrite: ^14.0.0
dev_dependencies:
flutter_lints: ^6.0.0
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
assets:
- assets/images/

30
test/widget_test.dart Normal file
View File

@@ -0,0 +1,30 @@
// 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:flutter_tank_web_app/main.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(const MyApp());
// 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);
});
}

BIN
web/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 917 B

BIN
web/icons/Icon-192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
web/icons/Icon-512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

38
web/index.html Normal file
View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<!--
If you are serving your web app in a path other than the root, change the
href value below to reflect the base path you are serving from.
The path provided below has to start and end with a slash "/" in order for
it to work correctly.
For more details:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
This is a placeholder for base href that will be replaced by the value of
the `--base-href` argument provided to `flutter build`.
-->
<base href="$FLUTTER_BASE_HREF">
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="A new Flutter project.">
<!-- iOS meta tags & icons -->
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="flutter_tank_web_app">
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png"/>
<title>flutter_tank_web_app</title>
<link rel="manifest" href="manifest.json">
</head>
<body>
<script src="flutter_bootstrap.js" async></script>
</body>
</html>

35
web/manifest.json Normal file
View File

@@ -0,0 +1,35 @@
{
"name": "flutter_tank_web_app",
"short_name": "flutter_tank_web_app",
"start_url": ".",
"display": "standalone",
"background_color": "#0175C2",
"theme_color": "#0175C2",
"description": "A new Flutter project.",
"orientation": "portrait-primary",
"prefer_related_applications": false,
"icons": [
{
"src": "icons/Icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icons/Icon-512.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "icons/Icon-maskable-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "icons/Icon-maskable-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
]
}