Base Flutter App
This commit is contained in:
parent
24c4adf910
commit
f59a5c06ba
5
web_native/.gitignore
vendored
5
web_native/.gitignore
vendored
@ -39,3 +39,8 @@ app.*.symbols
|
|||||||
|
|
||||||
# Obfuscation related
|
# Obfuscation related
|
||||||
app.*.map.json
|
app.*.map.json
|
||||||
|
|
||||||
|
# Android Studio will place build artifacts here
|
||||||
|
/android/app/debug
|
||||||
|
/android/app/profile
|
||||||
|
/android/app/release
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# This file should be version controlled and should not be manually edited.
|
# This file should be version controlled and should not be manually edited.
|
||||||
|
|
||||||
version:
|
version:
|
||||||
revision: 78910062997c3a836feee883712c241a5fd22983
|
revision: b0a22998593fc605c723dee8ff4d9315c32cfe2c
|
||||||
channel: stable
|
channel: beta
|
||||||
|
|
||||||
project_type: app
|
project_type: app
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Imagini
|
# imagini
|
||||||
|
|
||||||
A new Flutter project.
|
A new Flutter project.
|
||||||
|
|
||||||
|
@ -26,21 +26,17 @@ apply plugin: 'kotlin-android'
|
|||||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 29
|
compileSdkVersion 30
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
main.java.srcDirs += 'src/main/kotlin'
|
main.java.srcDirs += 'src/main/kotlin'
|
||||||
}
|
}
|
||||||
|
|
||||||
lintOptions {
|
|
||||||
disable 'InvalidPackage'
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||||
applicationId "com.reichard.imagini"
|
applicationId "com.reichard.imagini"
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 29
|
targetSdkVersion 30
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.example.web_native">
|
package="com.reichard.imagini">
|
||||||
<!-- Flutter needs it to communicate with the running application
|
<!-- Flutter needs it to communicate with the running application
|
||||||
to allow setting breakpoints, to provide hot reload, etc.
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
-->
|
-->
|
||||||
|
@ -1,13 +1,7 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.reichard.Imagini">
|
package="com.reichard.imagini">
|
||||||
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
<application
|
||||||
calls FlutterMain.startInitialization(this); in its onCreate method.
|
android:label="imagini"
|
||||||
In most cases you can leave this as-is, but you if you want to provide
|
|
||||||
additional functionality it is fine to subclass or reimplement
|
|
||||||
FlutterApplication and put your custom class here. -->
|
|
||||||
<application
|
|
||||||
android:name="io.flutter.app.FlutterApplication"
|
|
||||||
android:label="Imagini"
|
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/ic_launcher">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Modify this file to customize your launch splash screen -->
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="?android:colorBackground" />
|
||||||
|
|
||||||
|
<!-- You can insert your own image assets here -->
|
||||||
|
<!-- <item>
|
||||||
|
<bitmap
|
||||||
|
android:gravity="center"
|
||||||
|
android:src="@mipmap/launch_image" />
|
||||||
|
</item> -->
|
||||||
|
</layer-list>
|
18
web_native/android/app/src/main/res/values-night/styles.xml
Normal file
18
web_native/android/app/src/main/res/values-night/styles.xml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
||||||
|
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||||
|
<!-- Show a splash screen on the activity. Automatically removed when
|
||||||
|
Flutter draws its first frame -->
|
||||||
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
|
</style>
|
||||||
|
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||||
|
This theme determines the color of the Android Window while your
|
||||||
|
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||||
|
running.
|
||||||
|
|
||||||
|
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||||
|
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||||
|
<item name="android:windowBackground">?android:colorBackground</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Theme applied to the Android Window while the process is starting -->
|
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||||
<!-- Show a splash screen on the activity. Automatically removed when
|
<!-- Show a splash screen on the activity. Automatically removed when
|
||||||
Flutter draws its first frame -->
|
Flutter draws its first frame -->
|
||||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
@ -12,7 +12,7 @@
|
|||||||
running.
|
running.
|
||||||
|
|
||||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||||
<item name="android:windowBackground">@android:color/white</item>
|
<item name="android:windowBackground">?android:colorBackground</item>
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.reichard.Imagini">
|
package="com.reichard.imagini">
|
||||||
<!-- Flutter needs it to communicate with the running application
|
<!-- Flutter needs it to communicate with the running application
|
||||||
to allow setting breakpoints, to provide hot reload, etc.
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
-->
|
-->
|
||||||
|
@ -6,7 +6,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.5.0'
|
classpath 'com.android.tools.build:gradle:4.1.0'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
|
||||||
|
36
web_native/integration_test/app_test.dart
Normal file
36
web_native/integration_test/app_test.dart
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// This is a basic Flutter integration test.
|
||||||
|
//
|
||||||
|
// To perform an interaction with a widget in your test, use the WidgetTester
|
||||||
|
// utility that Flutter provides. 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:integration_test/integration_test.dart';
|
||||||
|
|
||||||
|
import 'package:imagini/main.dart' as app;
|
||||||
|
|
||||||
|
void main() => run(_testMain);
|
||||||
|
|
||||||
|
void _testMain() {
|
||||||
|
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||||
|
// Build our app and trigger a frame.
|
||||||
|
app.main();
|
||||||
|
|
||||||
|
// Trigger a frame.
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
});
|
||||||
|
}
|
8
web_native/integration_test/driver.dart
Normal file
8
web_native/integration_test/driver.dart
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// This file is provided as a convenience for running integration tests via the
|
||||||
|
// flutter drive command.
|
||||||
|
//
|
||||||
|
// flutter drive --driver integration_test/driver.dart --target integration_test/app_test.dart
|
||||||
|
|
||||||
|
import 'package:integration_test/integration_test_driver.dart';
|
||||||
|
|
||||||
|
Future<void> main() => integrationDriver();
|
@ -3,7 +3,7 @@
|
|||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<string>en</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>App</string>
|
<string>App</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
|
@ -1 +1,2 @@
|
|||||||
|
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||||
#include "Generated.xcconfig"
|
#include "Generated.xcconfig"
|
||||||
|
@ -1 +1,2 @@
|
|||||||
|
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||||
#include "Generated.xcconfig"
|
#include "Generated.xcconfig"
|
||||||
|
41
web_native/ios/Podfile
Normal file
41
web_native/ios/Podfile
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# Uncomment this line to define a global platform for your project
|
||||||
|
# platform :ios, '9.0'
|
||||||
|
|
||||||
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
|
||||||
|
project 'Runner', {
|
||||||
|
'Debug' => :debug,
|
||||||
|
'Profile' => :release,
|
||||||
|
'Release' => :release,
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutter_root
|
||||||
|
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
|
||||||
|
unless File.exist?(generated_xcode_build_settings_path)
|
||||||
|
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
|
||||||
|
end
|
||||||
|
|
||||||
|
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||||
|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||||
|
return matches[1].strip if matches
|
||||||
|
end
|
||||||
|
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
|
||||||
|
end
|
||||||
|
|
||||||
|
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||||
|
|
||||||
|
flutter_ios_podfile_setup
|
||||||
|
|
||||||
|
target 'Runner' do
|
||||||
|
use_frameworks!
|
||||||
|
use_modular_headers!
|
||||||
|
|
||||||
|
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||||
|
end
|
||||||
|
|
||||||
|
post_install do |installer|
|
||||||
|
installer.pods_project.targets.each do |target|
|
||||||
|
flutter_additional_ios_build_settings(target)
|
||||||
|
end
|
||||||
|
end
|
@ -289,17 +289,9 @@
|
|||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
"$(PROJECT_DIR)/Flutter",
|
|
||||||
);
|
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
LIBRARY_SEARCH_PATHS = (
|
PRODUCT_BUNDLE_IDENTIFIER = com.reichard.imagini;
|
||||||
"$(inherited)",
|
|
||||||
"$(PROJECT_DIR)/Flutter",
|
|
||||||
);
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.webNative;
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
@ -421,17 +413,9 @@
|
|||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
"$(PROJECT_DIR)/Flutter",
|
|
||||||
);
|
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
LIBRARY_SEARCH_PATHS = (
|
PRODUCT_BUNDLE_IDENTIFIER = com.reichard.imagini;
|
||||||
"$(inherited)",
|
|
||||||
"$(PROJECT_DIR)/Flutter",
|
|
||||||
);
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.webNative;
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
@ -448,17 +432,9 @@
|
|||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
"$(PROJECT_DIR)/Flutter",
|
|
||||||
);
|
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
LIBRARY_SEARCH_PATHS = (
|
PRODUCT_BUNDLE_IDENTIFIER = com.reichard.imagini;
|
||||||
"$(inherited)",
|
|
||||||
"$(PROJECT_DIR)/Flutter",
|
|
||||||
);
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.webNative;
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<string>6.0</string>
|
<string>6.0</string>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
<string>Imagini</string>
|
<string>imagini</string>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
|
68
web_native/lib/bloc/bloc-prov-tree.dart
Normal file
68
web_native/lib/bloc/bloc-prov-tree.dart
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:imagini/bloc/bloc-prov.dart';
|
||||||
|
|
||||||
|
/// A Flutter [Widget] that merges multiple [BlocProvider] widgets into one widget tree.
|
||||||
|
///
|
||||||
|
/// [BlocProviderTree] improves the readability and eliminates the need
|
||||||
|
/// to nest multiple [BlocProviders].
|
||||||
|
///
|
||||||
|
/// By using [BlocProviderTree] we can go from:
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// BlocProvider<BlocA>(
|
||||||
|
/// bloc: BlocA(),
|
||||||
|
/// child: BlocProvider<BlocB>(
|
||||||
|
/// bloc: BlocB(),
|
||||||
|
/// child: BlocProvider<BlocC>(
|
||||||
|
/// value: BlocC(),
|
||||||
|
/// child: ChildA(),
|
||||||
|
/// )
|
||||||
|
/// )
|
||||||
|
/// )
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// to:
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// BlocProviderTree(
|
||||||
|
/// blocProviders: [
|
||||||
|
/// BlocProvider<BlocA>(bloc: BlocA()),
|
||||||
|
/// BlocProvider<BlocB>(bloc: BlocB()),
|
||||||
|
/// BlocProvider<BlocC>(bloc: BlocC()),
|
||||||
|
/// ],
|
||||||
|
/// child: ChildA(),
|
||||||
|
/// )
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [BlocProviderTree] converts the [BlocProvider] list
|
||||||
|
/// into a tree of nested [BlocProvider] widgets.
|
||||||
|
/// As a result, the only advantage of using [BlocProviderTree] is improved
|
||||||
|
/// readability due to the reduction in nesting and boilerplate.
|
||||||
|
class BlocProviderTree extends StatelessWidget {
|
||||||
|
/// The [BlocProvider] list which is converted into a tree of [BlocProvider] widgets.
|
||||||
|
/// The tree of [BlocProvider] widgets is created in order meaning the first [BlocProvider]
|
||||||
|
/// will be the top-most [BlocProvider] and the last [BlocProvider] will be a direct ancestor
|
||||||
|
/// of the `child` [Widget].
|
||||||
|
final List<BlocProvider> blocProviders;
|
||||||
|
|
||||||
|
/// The [Widget] and its descendants which will have access to every [Bloc] provided by `blocProviders`.
|
||||||
|
/// This [Widget] will be a direct descendent of the last [BlocProvider] in `blocProviders`.
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
const BlocProviderTree({
|
||||||
|
Key key,
|
||||||
|
@required this.blocProviders,
|
||||||
|
@required this.child,
|
||||||
|
}) : assert(blocProviders != null),
|
||||||
|
assert(child != null),
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
Widget tree = child;
|
||||||
|
for (final blocProvider in blocProviders.reversed) {
|
||||||
|
tree = blocProvider.copyWith(tree);
|
||||||
|
}
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
}
|
60
web_native/lib/bloc/bloc-prov.dart
Normal file
60
web_native/lib/bloc/bloc-prov.dart
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:imagini/bloc/bloc.dart';
|
||||||
|
|
||||||
|
/// A Flutter widget which provides a bloc to its children via `BlocProvider.of(context)`.
|
||||||
|
/// It is used as a DI widget so that a single instance of a bloc can be provided
|
||||||
|
/// to multiple widgets within a subtree.
|
||||||
|
class BlocProvider<T extends Bloc> extends InheritedWidget {
|
||||||
|
/// The [Bloc] which is to be made available throughout the subtree
|
||||||
|
final T bloc;
|
||||||
|
|
||||||
|
/// The [Widget] and its descendants which will have access to the [Bloc].
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
BlocProvider({
|
||||||
|
Key key,
|
||||||
|
@required this.bloc,
|
||||||
|
this.child,
|
||||||
|
}) : assert(bloc != null),
|
||||||
|
super(key: key, child: child);
|
||||||
|
|
||||||
|
/// Method that allows widgets to access the bloc as long as their `BuildContext`
|
||||||
|
/// contains a `BlocProvider` instance.
|
||||||
|
static T of<T extends Bloc>(BuildContext context) {
|
||||||
|
final type = _typeOf<BlocProvider<T>>();
|
||||||
|
final BlocProvider<T> provider = context
|
||||||
|
.ancestorInheritedElementForWidgetOfExactType(type)
|
||||||
|
?.widget as BlocProvider<T>;
|
||||||
|
|
||||||
|
if (provider == null) {
|
||||||
|
throw FlutterError(
|
||||||
|
"""
|
||||||
|
BlocProvider.of() called with a context that does not contain a Bloc of type $T.
|
||||||
|
No ancestor could be found starting from the context that was passed to BlocProvider.of<$T>().
|
||||||
|
This can happen if the context you use comes from a widget above the BlocProvider.
|
||||||
|
This can also happen if you used BlocProviderTree and didn\'t explicity provide
|
||||||
|
the BlocProvider types: BlocProvider(bloc: $T()) instead of BlocProvider<$T>(bloc: $T()).
|
||||||
|
The context used was: $context
|
||||||
|
""",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return provider?.bloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clone the current [BlocProvider] with a new child [Widget].
|
||||||
|
/// All other values, including [Key] and [Bloc] are preserved.
|
||||||
|
BlocProvider<T> copyWith(Widget child) {
|
||||||
|
return BlocProvider<T>(
|
||||||
|
key: key,
|
||||||
|
bloc: bloc,
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Necessary to obtain generic [Type]
|
||||||
|
/// https://github.com/dart-lang/sdk/issues/11923
|
||||||
|
static Type _typeOf<T>() => T;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool updateShouldNotify(BlocProvider oldWidget) => false;
|
||||||
|
}
|
1
web_native/lib/bloc/bloc.dart
Normal file
1
web_native/lib/bloc/bloc.dart
Normal file
@ -0,0 +1 @@
|
|||||||
|
abstract class Bloc {}
|
5
web_native/lib/blocs/auth-bloc.dart
Normal file
5
web_native/lib/blocs/auth-bloc.dart
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import 'package:imagini/bloc/bloc.dart';
|
||||||
|
|
||||||
|
class AuthBloc extends Bloc {
|
||||||
|
AuthBloc();
|
||||||
|
}
|
2
web_native/lib/blocs/blocs.dart
Normal file
2
web_native/lib/blocs/blocs.dart
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export 'auth-bloc.dart';
|
||||||
|
export 'pref-bloc.dart';
|
5
web_native/lib/blocs/pref-bloc.dart
Normal file
5
web_native/lib/blocs/pref-bloc.dart
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import 'package:imagini/bloc/bloc.dart';
|
||||||
|
|
||||||
|
class PrefBloc extends Bloc {
|
||||||
|
PrefBloc();
|
||||||
|
}
|
636
web_native/lib/components/roundedalertdialog.dart
Normal file
636
web_native/lib/components/roundedalertdialog.dart
Normal file
@ -0,0 +1,636 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
// Examples can assume:
|
||||||
|
// enum Department { treasury, state }
|
||||||
|
|
||||||
|
/// A material design dialog.
|
||||||
|
///
|
||||||
|
/// This dialog widget does not have any opinion about the contents of the
|
||||||
|
/// dialog. Rather than using this widget directly, consider using [AlertDialog]
|
||||||
|
/// or [SimpleDialog], which implement specific kinds of material design
|
||||||
|
/// dialogs.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [AlertDialog], for dialogs that have a message and some buttons.
|
||||||
|
/// * [SimpleDialog], for dialogs that offer a variety of options.
|
||||||
|
/// * [showDialog], which actually displays the dialog and returns its result.
|
||||||
|
/// * <https://material.google.com/components/dialogs.html>
|
||||||
|
class Dialog extends StatelessWidget {
|
||||||
|
/// Creates a dialog.
|
||||||
|
///
|
||||||
|
/// Typically used in conjunction with [showDialog].
|
||||||
|
const Dialog({
|
||||||
|
Key key,
|
||||||
|
this.child,
|
||||||
|
this.insetAnimationDuration: const Duration(milliseconds: 100),
|
||||||
|
this.insetAnimationCurve: Curves.decelerate,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
/// The widget below this widget in the tree.
|
||||||
|
///
|
||||||
|
/// {@macro flutter.widgets.child}
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
/// The duration of the animation to show when the system keyboard intrudes
|
||||||
|
/// into the space that the dialog is placed in.
|
||||||
|
///
|
||||||
|
/// Defaults to 100 milliseconds.
|
||||||
|
final Duration insetAnimationDuration;
|
||||||
|
|
||||||
|
/// The curve to use for the animation shown when the system keyboard intrudes
|
||||||
|
/// into the space that the dialog is placed in.
|
||||||
|
///
|
||||||
|
/// Defaults to [Curves.fastOutSlowIn].
|
||||||
|
final Curve insetAnimationCurve;
|
||||||
|
|
||||||
|
Color _getColor(BuildContext context) {
|
||||||
|
return Theme.of(context).dialogBackgroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new AnimatedPadding(
|
||||||
|
padding: MediaQuery.of(context).viewInsets +
|
||||||
|
const EdgeInsets.symmetric(horizontal: 40.0, vertical: 24.0),
|
||||||
|
duration: insetAnimationDuration,
|
||||||
|
curve: insetAnimationCurve,
|
||||||
|
child: new MediaQuery.removeViewInsets(
|
||||||
|
removeLeft: true,
|
||||||
|
removeTop: true,
|
||||||
|
removeRight: true,
|
||||||
|
removeBottom: true,
|
||||||
|
context: context,
|
||||||
|
child: new Center(
|
||||||
|
child: new ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(minWidth: 280.0),
|
||||||
|
child: new Material(
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), side: BorderSide(color: Colors.white, width: 1.0, style: BorderStyle.solid)),
|
||||||
|
elevation: 30.0,
|
||||||
|
color: _getColor(context),
|
||||||
|
type: MaterialType.card,
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A material design alert dialog.
|
||||||
|
///
|
||||||
|
/// An alert dialog informs the user about situations that require
|
||||||
|
/// acknowledgement. An alert dialog has an optional title and an optional list
|
||||||
|
/// of actions. The title is displayed above the content and the actions are
|
||||||
|
/// displayed below the content.
|
||||||
|
///
|
||||||
|
/// If the content is too large to fit on the screen vertically, the dialog will
|
||||||
|
/// display the title and the actions and let the content overflow. Consider
|
||||||
|
/// using a scrolling widget, such as [ListView], for [content] to avoid
|
||||||
|
/// overflow.
|
||||||
|
///
|
||||||
|
/// For dialogs that offer the user a choice between several options, consider
|
||||||
|
/// using a [SimpleDialog].
|
||||||
|
///
|
||||||
|
/// Typically passed as the child widget to [showDialog], which displays the
|
||||||
|
/// dialog.
|
||||||
|
///
|
||||||
|
/// ## Sample code
|
||||||
|
///
|
||||||
|
/// This snippet shows a method in a [State] which, when called, displays a dialog box
|
||||||
|
/// and returns a [Future] that completes when the dialog is dismissed.
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// Future<Null> _neverSatisfied() async {
|
||||||
|
/// return showDialog<Null>(
|
||||||
|
/// context: context,
|
||||||
|
/// barrierDismissible: false, // user must tap button!
|
||||||
|
/// builder: (BuildContext context) {
|
||||||
|
/// return new AlertDialog(
|
||||||
|
/// title: new Text('Rewind and remember'),
|
||||||
|
/// content: new SingleChildScrollView(
|
||||||
|
/// child: new ListBody(
|
||||||
|
/// children: <Widget>[
|
||||||
|
/// new Text('You will never be satisfied.'),
|
||||||
|
/// new Text('You\’re like me. I’m never satisfied.'),
|
||||||
|
/// ],
|
||||||
|
/// ),
|
||||||
|
/// ),
|
||||||
|
/// actions: <Widget>[
|
||||||
|
/// new FlatButton(
|
||||||
|
/// child: new Text('Regret'),
|
||||||
|
/// onPressed: () {
|
||||||
|
/// Navigator.of(context).pop();
|
||||||
|
/// },
|
||||||
|
/// ),
|
||||||
|
/// ],
|
||||||
|
/// );
|
||||||
|
/// },
|
||||||
|
/// );
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [SimpleDialog], which handles the scrolling of the contents but has no [actions].
|
||||||
|
/// * [Dialog], on which [AlertDialog] and [SimpleDialog] are based.
|
||||||
|
/// * [showDialog], which actually displays the dialog and returns its result.
|
||||||
|
/// * <https://material.google.com/components/dialogs.html#dialogs-alerts>
|
||||||
|
class CustomAlertDialog extends StatelessWidget {
|
||||||
|
/// Creates an alert dialog.
|
||||||
|
///
|
||||||
|
/// Typically used in conjunction with [showDialog].
|
||||||
|
///
|
||||||
|
/// The [contentPadding] must not be null. The [titlePadding] defaults to
|
||||||
|
/// null, which implies a default that depends on the values of the other
|
||||||
|
/// properties. See the documentation of [titlePadding] for details.
|
||||||
|
const CustomAlertDialog({
|
||||||
|
Key key,
|
||||||
|
this.title,
|
||||||
|
this.titlePadding,
|
||||||
|
this.content,
|
||||||
|
this.contentPadding: const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 24.0),
|
||||||
|
this.actions,
|
||||||
|
this.semanticLabel,
|
||||||
|
}) : assert(contentPadding != null),
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
|
/// The (optional) title of the dialog is displayed in a large font at the top
|
||||||
|
/// of the dialog.
|
||||||
|
///
|
||||||
|
/// Typically a [Text] widget.
|
||||||
|
final Widget title;
|
||||||
|
|
||||||
|
/// Padding around the title.
|
||||||
|
///
|
||||||
|
/// If there is no title, no padding will be provided. Otherwise, this padding
|
||||||
|
/// is used.
|
||||||
|
///
|
||||||
|
/// This property defaults to providing 24 pixels on the top, left, and right
|
||||||
|
/// of the title. If the [content] is not null, then no bottom padding is
|
||||||
|
/// provided (but see [contentPadding]). If it _is_ null, then an extra 20
|
||||||
|
/// pixels of bottom padding is added to separate the [title] from the
|
||||||
|
/// [actions].
|
||||||
|
final EdgeInsetsGeometry titlePadding;
|
||||||
|
|
||||||
|
/// The (optional) content of the dialog is displayed in the center of the
|
||||||
|
/// dialog in a lighter font.
|
||||||
|
///
|
||||||
|
/// Typically, this is a [ListView] containing the contents of the dialog.
|
||||||
|
/// Using a [ListView] ensures that the contents can scroll if they are too
|
||||||
|
/// big to fit on the display.
|
||||||
|
final Widget content;
|
||||||
|
|
||||||
|
/// Padding around the content.
|
||||||
|
///
|
||||||
|
/// If there is no content, no padding will be provided. Otherwise, padding of
|
||||||
|
/// 20 pixels is provided above the content to separate the content from the
|
||||||
|
/// title, and padding of 24 pixels is provided on the left, right, and bottom
|
||||||
|
/// to separate the content from the other edges of the dialog.
|
||||||
|
final EdgeInsetsGeometry contentPadding;
|
||||||
|
|
||||||
|
/// The (optional) set of actions that are displayed at the bottom of the
|
||||||
|
/// dialog.
|
||||||
|
///
|
||||||
|
/// Typically this is a list of [FlatButton] widgets.
|
||||||
|
///
|
||||||
|
/// These widgets will be wrapped in a [ButtonBar], which introduces 8 pixels
|
||||||
|
/// of padding on each side.
|
||||||
|
///
|
||||||
|
/// If the [title] is not null but the [content] _is_ null, then an extra 20
|
||||||
|
/// pixels of padding is added above the [ButtonBar] to separate the [title]
|
||||||
|
/// from the [actions].
|
||||||
|
final List<Widget> actions;
|
||||||
|
|
||||||
|
/// The semantic label of the dialog used by accessibility frameworks to
|
||||||
|
/// announce screen transitions when the dialog is opened and closed.
|
||||||
|
///
|
||||||
|
/// If this label is not provided, a semantic label will be infered from the
|
||||||
|
/// [title] if it is not null. If there is no title, the label will be taken
|
||||||
|
/// from [MaterialLocalizations.alertDialogLabel].
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [SemanticsConfiguration.isRouteName], for a description of how this
|
||||||
|
/// value is used.
|
||||||
|
final String semanticLabel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final List<Widget> children = <Widget>[];
|
||||||
|
String label = semanticLabel;
|
||||||
|
|
||||||
|
if (title != null) {
|
||||||
|
children.add(new Padding(
|
||||||
|
padding: titlePadding ??
|
||||||
|
new EdgeInsets.fromLTRB(
|
||||||
|
24.0, 24.0, 24.0, content == null ? 20.0 : 0.0),
|
||||||
|
child: new DefaultTextStyle(
|
||||||
|
style: Theme.of(context).textTheme.title,
|
||||||
|
child: new Semantics(child: title, namesRoute: true),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
switch (defaultTargetPlatform) {
|
||||||
|
case TargetPlatform.iOS:
|
||||||
|
label = semanticLabel;
|
||||||
|
break;
|
||||||
|
case TargetPlatform.android:
|
||||||
|
case TargetPlatform.fuchsia:
|
||||||
|
label = semanticLabel ??
|
||||||
|
MaterialLocalizations.of(context)?.alertDialogLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (content != null) {
|
||||||
|
children.add(new Flexible(
|
||||||
|
child: new Padding(
|
||||||
|
padding: contentPadding,
|
||||||
|
child: new DefaultTextStyle(
|
||||||
|
style: Theme.of(context).textTheme.subhead,
|
||||||
|
child: content,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actions != null) {
|
||||||
|
children.add(new ButtonTheme.bar(
|
||||||
|
child: new ButtonBar(
|
||||||
|
children: actions,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget dialogChild = new IntrinsicWidth(
|
||||||
|
child: new Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: children,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (label != null)
|
||||||
|
dialogChild =
|
||||||
|
new Semantics(namesRoute: true, label: label, child: dialogChild);
|
||||||
|
|
||||||
|
return new Dialog(child: dialogChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An option used in a [SimpleDialog].
|
||||||
|
///
|
||||||
|
/// A simple dialog offers the user a choice between several options. This
|
||||||
|
/// widget is commonly used to represent each of the options. If the user
|
||||||
|
/// selects this option, the widget will call the [onPressed] callback, which
|
||||||
|
/// typically uses [Navigator.pop] to close the dialog.
|
||||||
|
///
|
||||||
|
/// The padding on a [SimpleDialogOption] is configured to combine with the
|
||||||
|
/// default [SimpleDialog.contentPadding] so that each option ends up 8 pixels
|
||||||
|
/// from the other vertically, with 20 pixels of spacing between the dialog's
|
||||||
|
/// title and the first option, and 24 pixels of spacing between the last option
|
||||||
|
/// and the bottom of the dialog.
|
||||||
|
///
|
||||||
|
/// ## Sample code
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// new SimpleDialogOption(
|
||||||
|
/// onPressed: () { Navigator.pop(context, Department.treasury); },
|
||||||
|
/// child: const Text('Treasury department'),
|
||||||
|
/// )
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [SimpleDialog], for a dialog in which to use this widget.
|
||||||
|
/// * [showDialog], which actually displays the dialog and returns its result.
|
||||||
|
/// * [FlatButton], which are commonly used as actions in other kinds of
|
||||||
|
/// dialogs, such as [AlertDialog]s.
|
||||||
|
/// * <https://material.google.com/components/dialogs.html#dialogs-simple-dialogs>
|
||||||
|
class SimpleDialogOption extends StatelessWidget {
|
||||||
|
/// Creates an option for a [SimpleDialog].
|
||||||
|
const SimpleDialogOption({
|
||||||
|
Key key,
|
||||||
|
this.onPressed,
|
||||||
|
this.child,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
/// The callback that is called when this option is selected.
|
||||||
|
///
|
||||||
|
/// If this is set to null, the option cannot be selected.
|
||||||
|
///
|
||||||
|
/// When used in a [SimpleDialog], this will typically call [Navigator.pop]
|
||||||
|
/// with a value for [showDialog] to complete its future with.
|
||||||
|
final VoidCallback onPressed;
|
||||||
|
|
||||||
|
/// The widget below this widget in the tree.
|
||||||
|
///
|
||||||
|
/// Typically a [Text] widget.
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new InkWell(
|
||||||
|
onTap: onPressed,
|
||||||
|
child: new Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 24.0),
|
||||||
|
child: child),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A simple material design dialog.
|
||||||
|
///
|
||||||
|
/// A simple dialog offers the user a choice between several options. A simple
|
||||||
|
/// dialog has an optional title that is displayed above the choices.
|
||||||
|
///
|
||||||
|
/// Choices are normally represented using [SimpleDialogOption] widgets. If
|
||||||
|
/// other widgets are used, see [contentPadding] for notes regarding the
|
||||||
|
/// conventions for obtaining the spacing expected by Material Design.
|
||||||
|
///
|
||||||
|
/// For dialogs that inform the user about a situation, consider using an
|
||||||
|
/// [AlertDialog].
|
||||||
|
///
|
||||||
|
/// Typically passed as the child widget to [showDialog], which displays the
|
||||||
|
/// dialog.
|
||||||
|
///
|
||||||
|
/// ## Sample code
|
||||||
|
///
|
||||||
|
/// In this example, the user is asked to select between two options. These
|
||||||
|
/// options are represented as an enum. The [showDialog] method here returns
|
||||||
|
/// a [Future] that completes to a value of that enum. If the user cancels
|
||||||
|
/// the dialog (e.g. by hitting the back button on Android, or tapping on the
|
||||||
|
/// mask behind the dialog) then the future completes with the null value.
|
||||||
|
///
|
||||||
|
/// The return value in this example is used as the index for a switch statement.
|
||||||
|
/// One advantage of using an enum as the return value and then using that to
|
||||||
|
/// drive a switch statement is that the analyzer will flag any switch statement
|
||||||
|
/// that doesn't mention every value in the enum.
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// Future<Null> _askedToLead() async {
|
||||||
|
/// switch (await showDialog<Department>(
|
||||||
|
/// context: context,
|
||||||
|
/// builder: (BuildContext context) {
|
||||||
|
/// return new SimpleDialog(
|
||||||
|
/// title: const Text('Select assignment'),
|
||||||
|
/// children: <Widget>[
|
||||||
|
/// new SimpleDialogOption(
|
||||||
|
/// onPressed: () { Navigator.pop(context, Department.treasury); },
|
||||||
|
/// child: const Text('Treasury department'),
|
||||||
|
/// ),
|
||||||
|
/// new SimpleDialogOption(
|
||||||
|
/// onPressed: () { Navigator.pop(context, Department.state); },
|
||||||
|
/// child: const Text('State department'),
|
||||||
|
/// ),
|
||||||
|
/// ],
|
||||||
|
/// );
|
||||||
|
/// }
|
||||||
|
/// )) {
|
||||||
|
/// case Department.treasury:
|
||||||
|
/// // Let's go.
|
||||||
|
/// // ...
|
||||||
|
/// break;
|
||||||
|
/// case Department.state:
|
||||||
|
/// // ...
|
||||||
|
/// break;
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [SimpleDialogOption], which are options used in this type of dialog.
|
||||||
|
/// * [AlertDialog], for dialogs that have a row of buttons below the body.
|
||||||
|
/// * [Dialog], on which [SimpleDialog] and [AlertDialog] are based.
|
||||||
|
/// * [showDialog], which actually displays the dialog and returns its result.
|
||||||
|
/// * <https://material.google.com/components/dialogs.html#dialogs-simple-dialogs>
|
||||||
|
class SimpleDialog extends StatelessWidget {
|
||||||
|
/// Creates a simple dialog.
|
||||||
|
///
|
||||||
|
/// Typically used in conjunction with [showDialog].
|
||||||
|
///
|
||||||
|
/// The [titlePadding] and [contentPadding] arguments must not be null.
|
||||||
|
const SimpleDialog({
|
||||||
|
Key key,
|
||||||
|
this.title,
|
||||||
|
this.titlePadding: const EdgeInsets.fromLTRB(24.0, 24.0, 24.0, 0.0),
|
||||||
|
this.children,
|
||||||
|
this.contentPadding: const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 16.0),
|
||||||
|
this.semanticLabel,
|
||||||
|
}) : assert(titlePadding != null),
|
||||||
|
assert(contentPadding != null),
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
|
/// The (optional) title of the dialog is displayed in a large font at the top
|
||||||
|
/// of the dialog.
|
||||||
|
///
|
||||||
|
/// Typically a [Text] widget.
|
||||||
|
final Widget title;
|
||||||
|
|
||||||
|
/// Padding around the title.
|
||||||
|
///
|
||||||
|
/// If there is no title, no padding will be provided.
|
||||||
|
///
|
||||||
|
/// By default, this provides the recommend Material Design padding of 24
|
||||||
|
/// pixels around the left, top, and right edges of the title.
|
||||||
|
///
|
||||||
|
/// See [contentPadding] for the conventions regarding padding between the
|
||||||
|
/// [title] and the [children].
|
||||||
|
final EdgeInsetsGeometry titlePadding;
|
||||||
|
|
||||||
|
/// The (optional) content of the dialog is displayed in a
|
||||||
|
/// [SingleChildScrollView] underneath the title.
|
||||||
|
///
|
||||||
|
/// Typically a list of [SimpleDialogOption]s.
|
||||||
|
final List<Widget> children;
|
||||||
|
|
||||||
|
/// Padding around the content.
|
||||||
|
///
|
||||||
|
/// By default, this is 12 pixels on the top and 16 pixels on the bottom. This
|
||||||
|
/// is intended to be combined with children that have 24 pixels of padding on
|
||||||
|
/// the left and right, and 8 pixels of padding on the top and bottom, so that
|
||||||
|
/// the content ends up being indented 20 pixels from the title, 24 pixels
|
||||||
|
/// from the bottom, and 24 pixels from the sides.
|
||||||
|
///
|
||||||
|
/// The [SimpleDialogOption] widget uses such padding.
|
||||||
|
///
|
||||||
|
/// If there is no [title], the [contentPadding] should be adjusted so that
|
||||||
|
/// the top padding ends up being 24 pixels.
|
||||||
|
final EdgeInsetsGeometry contentPadding;
|
||||||
|
|
||||||
|
/// The semantic label of the dialog used by accessibility frameworks to
|
||||||
|
/// announce screen transitions when the dialog is opened and closed.
|
||||||
|
///
|
||||||
|
/// If this label is not provided, a semantic label will be infered from the
|
||||||
|
/// [title] if it is not null. If there is no title, the label will be taken
|
||||||
|
/// from [MaterialLocalizations.dialogLabel].
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [SemanticsConfiguration.isRouteName], for a description of how this
|
||||||
|
/// value is used.
|
||||||
|
final String semanticLabel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final List<Widget> body = <Widget>[];
|
||||||
|
String label = semanticLabel;
|
||||||
|
|
||||||
|
if (title != null) {
|
||||||
|
body.add(new Padding(
|
||||||
|
padding: titlePadding,
|
||||||
|
child: new DefaultTextStyle(
|
||||||
|
style: Theme.of(context).textTheme.title,
|
||||||
|
child: new Semantics(namesRoute: true, child: title),
|
||||||
|
)));
|
||||||
|
} else {
|
||||||
|
switch (defaultTargetPlatform) {
|
||||||
|
case TargetPlatform.iOS:
|
||||||
|
label = semanticLabel;
|
||||||
|
break;
|
||||||
|
case TargetPlatform.android:
|
||||||
|
case TargetPlatform.fuchsia:
|
||||||
|
label =
|
||||||
|
semanticLabel ?? MaterialLocalizations.of(context)?.dialogLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (children != null) {
|
||||||
|
body.add(new Flexible(
|
||||||
|
child: new SingleChildScrollView(
|
||||||
|
padding: contentPadding,
|
||||||
|
child: new ListBody(children: children),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget dialogChild = new IntrinsicWidth(
|
||||||
|
stepWidth: 56.0,
|
||||||
|
child: new ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(minWidth: 280.0),
|
||||||
|
child: new Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: body,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (label != null)
|
||||||
|
dialogChild = new Semantics(
|
||||||
|
namesRoute: true,
|
||||||
|
label: label,
|
||||||
|
child: dialogChild,
|
||||||
|
);
|
||||||
|
return new Dialog(child: dialogChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DialogRoute<T> extends PopupRoute<T> {
|
||||||
|
_DialogRoute({
|
||||||
|
@required this.theme,
|
||||||
|
bool barrierDismissible: true,
|
||||||
|
this.barrierLabel,
|
||||||
|
@required this.child,
|
||||||
|
RouteSettings settings,
|
||||||
|
}) : assert(barrierDismissible != null),
|
||||||
|
_barrierDismissible = barrierDismissible,
|
||||||
|
super(settings: settings);
|
||||||
|
|
||||||
|
final Widget child;
|
||||||
|
final ThemeData theme;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Duration get transitionDuration => const Duration(milliseconds: 150);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get barrierDismissible => _barrierDismissible;
|
||||||
|
final bool _barrierDismissible;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color get barrierColor => Colors.black54;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String barrierLabel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget buildPage(BuildContext context, Animation<double> animation,
|
||||||
|
Animation<double> secondaryAnimation) {
|
||||||
|
return new SafeArea(
|
||||||
|
child: new Builder(builder: (BuildContext context) {
|
||||||
|
final Widget annotatedChild = new Semantics(
|
||||||
|
child: child,
|
||||||
|
scopesRoute: true,
|
||||||
|
explicitChildNodes: true,
|
||||||
|
);
|
||||||
|
return theme != null
|
||||||
|
? new Theme(data: theme, child: annotatedChild)
|
||||||
|
: annotatedChild;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget buildTransitions(BuildContext context, Animation<double> animation,
|
||||||
|
Animation<double> secondaryAnimation, Widget child) {
|
||||||
|
return new FadeTransition(
|
||||||
|
opacity: new CurvedAnimation(parent: animation, curve: Curves.easeOut),
|
||||||
|
child: child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Displays a dialog above the current contents of the app.
|
||||||
|
///
|
||||||
|
/// This function takes a `builder` which typically builds a [Dialog] widget.
|
||||||
|
/// Content below the dialog is dimmed with a [ModalBarrier]. This widget does
|
||||||
|
/// not share a context with the location that `showDialog` is originally
|
||||||
|
/// called from. Use a [StatefulBuilder] or a custom [StatefulWidget] if the
|
||||||
|
/// dialog needs to update dynamically.
|
||||||
|
///
|
||||||
|
/// The `context` argument is used to look up the [Navigator] and [Theme] for
|
||||||
|
/// the dialog. It is only used when the method is called. Its corresponding
|
||||||
|
/// widget can be safely removed from the tree before the dialog is closed.
|
||||||
|
///
|
||||||
|
/// The `child` argument is deprecated, and should be replaced with `builder`.
|
||||||
|
///
|
||||||
|
/// Returns a [Future] that resolves to the value (if any) that was passed to
|
||||||
|
/// [Navigator.pop] when the dialog was closed.
|
||||||
|
///
|
||||||
|
/// The dialog route created by this method is pushed to the root navigator.
|
||||||
|
/// If the application has multiple [Navigator] objects, it may be necessary to
|
||||||
|
/// call `Navigator.of(context, rootNavigator: true).pop(result)` to close the
|
||||||
|
/// dialog rather just 'Navigator.pop(context, result)`.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
/// * [AlertDialog], for dialogs that have a row of buttons below a body.
|
||||||
|
/// * [SimpleDialog], which handles the scrolling of the contents and does
|
||||||
|
/// not show buttons below its body.
|
||||||
|
/// * [Dialog], on which [SimpleDialog] and [AlertDialog] are based.
|
||||||
|
/// * <https://material.google.com/components/dialogs.html>
|
||||||
|
Future<T> customShowDialog<T>({
|
||||||
|
@required
|
||||||
|
BuildContext context,
|
||||||
|
bool barrierDismissible: true,
|
||||||
|
@Deprecated(
|
||||||
|
'Instead of using the "child" argument, return the child from a closure '
|
||||||
|
'provided to the "builder" argument. This will ensure that the BuildContext '
|
||||||
|
'is appropriate for widgets built in the dialog.')
|
||||||
|
Widget child,
|
||||||
|
WidgetBuilder builder,
|
||||||
|
}) {
|
||||||
|
assert(child == null || builder == null);
|
||||||
|
return Navigator.of(context, rootNavigator: true).push(new _DialogRoute<T>(
|
||||||
|
child: child ?? new Builder(builder: builder),
|
||||||
|
theme: Theme.of(context, shadowThemeOnly: true),
|
||||||
|
barrierDismissible: barrierDismissible,
|
||||||
|
barrierLabel:
|
||||||
|
MaterialLocalizations.of(context).modalBarrierDismissLabel,
|
||||||
|
));
|
||||||
|
}
|
@ -1,117 +1,28 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:imagini/theme/style.dart';
|
||||||
|
import 'package:imagini/routes.dart';
|
||||||
|
import 'package:imagini/bloc/bloc-prov-tree.dart';
|
||||||
|
import 'package:imagini/bloc/bloc-prov.dart';
|
||||||
|
import 'package:imagini/blocs/blocs.dart';
|
||||||
|
import 'blocs/blocs.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(MyApp());
|
runApp(ExampleApp());
|
||||||
}
|
}
|
||||||
|
class ExampleApp extends StatelessWidget {
|
||||||
class MyApp extends StatelessWidget {
|
|
||||||
// This widget is the root of your application.
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return BlocProviderTree(
|
||||||
title: 'Flutter Demo',
|
blocProviders: <BlocProvider>[
|
||||||
theme: ThemeData(
|
BlocProvider<AuthBloc>(bloc: AuthBloc()),
|
||||||
// This is the theme of your application.
|
BlocProvider<PrefBloc>(bloc: PrefBloc()),
|
||||||
//
|
],
|
||||||
// Try running your application with "flutter run". You'll see the
|
child: MaterialApp(
|
||||||
// application has a blue toolbar. Then, without quitting the app, try
|
title: 'ExampleApp',
|
||||||
// changing the primarySwatch below to Colors.green and then invoke
|
theme: appTheme(),
|
||||||
// "hot reload" (press "r" in the console where you ran "flutter run",
|
initialRoute: '/',
|
||||||
// or simply save your changes to "hot reload" in a Flutter IDE).
|
routes: routes,
|
||||||
// Notice that the counter didn't reset back to zero; the application
|
|
||||||
// is not restarted.
|
|
||||||
primarySwatch: Colors.blue,
|
|
||||||
// This makes the visual density adapt to the platform that you run
|
|
||||||
// the app on. For desktop platforms, the controls will be smaller and
|
|
||||||
// closer together (more dense) than on mobile platforms.
|
|
||||||
visualDensity: VisualDensity.adaptivePlatformDensity,
|
|
||||||
),
|
),
|
||||||
home: MyHomePage(title: 'Flutter Demo Home Page'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MyHomePage extends StatefulWidget {
|
|
||||||
MyHomePage({Key key, this.title}) : super(key: key);
|
|
||||||
|
|
||||||
// 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
|
|
||||||
_MyHomePageState 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(
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// Invoke "debug painting" (press "p" in the console, choose the
|
|
||||||
// "Toggle Debug Paint" action from the Flutter Inspector in Android
|
|
||||||
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
|
|
||||||
// to see the wireframe for each widget.
|
|
||||||
//
|
|
||||||
// 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).
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
|
||||||
Text(
|
|
||||||
'You have pushed the button this many times:',
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
'$_counter',
|
|
||||||
style: Theme.of(context).textTheme.headline4,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
floatingActionButton: FloatingActionButton(
|
|
||||||
onPressed: _incrementCounter,
|
|
||||||
tooltip: 'Increment',
|
|
||||||
child: Icon(Icons.add),
|
|
||||||
), // This trailing comma makes auto-formatting nicer for build methods.
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
113
web_native/lib/main.dart.bak
Normal file
113
web_native/lib/main.dart.bak
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
runApp(MyApp());
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyApp extends StatelessWidget {
|
||||||
|
// This widget is the root of your application.
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MaterialApp(
|
||||||
|
title: 'Flutter Demo',
|
||||||
|
theme: ThemeData(
|
||||||
|
// This is the theme of your application.
|
||||||
|
//
|
||||||
|
// Try running your application with "flutter run". You'll see the
|
||||||
|
// application has a blue toolbar. Then, without quitting the app, try
|
||||||
|
// changing the primarySwatch below to Colors.green and then invoke
|
||||||
|
// "hot reload" (press "r" in the console where you ran "flutter run",
|
||||||
|
// or simply save your changes to "hot reload" in a Flutter IDE).
|
||||||
|
// Notice that the counter didn't reset back to zero; the application
|
||||||
|
// is not restarted.
|
||||||
|
primarySwatch: Colors.blue,
|
||||||
|
),
|
||||||
|
home: MyHomePage(title: 'Flutter Demo Home Page'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyHomePage extends StatefulWidget {
|
||||||
|
MyHomePage({Key key, this.title}) : super(key: key);
|
||||||
|
|
||||||
|
// 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
|
||||||
|
_MyHomePageState 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(
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Invoke "debug painting" (press "p" in the console, choose the
|
||||||
|
// "Toggle Debug Paint" action from the Flutter Inspector in Android
|
||||||
|
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
|
||||||
|
// to see the wireframe for each widget.
|
||||||
|
//
|
||||||
|
// 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).
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Text(
|
||||||
|
'You have pushed the button this many times:',
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'$_counter',
|
||||||
|
style: Theme.of(context).textTheme.headline4,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
floatingActionButton: FloatingActionButton(
|
||||||
|
onPressed: _incrementCounter,
|
||||||
|
tooltip: 'Increment',
|
||||||
|
child: Icon(Icons.add),
|
||||||
|
), // This trailing comma makes auto-formatting nicer for build methods.
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
8
web_native/lib/models/contact.dart
Normal file
8
web_native/lib/models/contact.dart
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
|
class Contact {
|
||||||
|
final String avatarUrl;
|
||||||
|
final String name;
|
||||||
|
|
||||||
|
Contact({@required this.avatarUrl, @required this.name});
|
||||||
|
}
|
8
web_native/lib/routes.dart
Normal file
8
web_native/lib/routes.dart
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:imagini/screens/example1/examplescreen1.dart';
|
||||||
|
import 'package:imagini/screens/example2/examplescreen2.dart';
|
||||||
|
|
||||||
|
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||||
|
"/": (BuildContext context) => ExScreen1(),
|
||||||
|
"/ExScreen2": (BuildContext context) => ExScreen2(),
|
||||||
|
};
|
15
web_native/lib/screens/example1/components/body.dart
Normal file
15
web_native/lib/screens/example1/components/body.dart
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class Body extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Center(
|
||||||
|
child: RaisedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: Text('Go back!'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
20
web_native/lib/screens/example1/example-bloc.dart
Normal file
20
web_native/lib/screens/example1/example-bloc.dart
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:ui';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:imagini/models/contact.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:imagini/bloc/bloc.dart';
|
||||||
|
|
||||||
|
class ExampleBloc extends Bloc {
|
||||||
|
StreamSubscription _audioPlayerStateSubscription;
|
||||||
|
|
||||||
|
Stream<String> get example => _exampleSubject.stream;
|
||||||
|
Sink<String> get exampleSink => _exampleSubject.sink;
|
||||||
|
final StreamController<String> _exampleSubject = StreamController<String>();
|
||||||
|
|
||||||
|
ExampleBloc();
|
||||||
|
|
||||||
|
void dispose() {
|
||||||
|
_exampleSubject.close();
|
||||||
|
}
|
||||||
|
}
|
40
web_native/lib/screens/example1/examplescreen1.dart
Normal file
40
web_native/lib/screens/example1/examplescreen1.dart
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:imagini/screens/example1/components/body.dart';
|
||||||
|
import 'package:imagini/screens/example1/example-bloc.dart';
|
||||||
|
import 'package:imagini/bloc/bloc-prov.dart';
|
||||||
|
|
||||||
|
class ExScreen1 extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_ExScreen1State createState() => _ExScreen1State();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ExScreen1State extends State<ExScreen1> {
|
||||||
|
ExampleBloc exampleBloc;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
exampleBloc = ExampleBloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
exampleBloc.dispose();
|
||||||
|
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider(
|
||||||
|
bloc: exampleBloc,
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text("First Screen"),
|
||||||
|
),
|
||||||
|
body: Body(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
15
web_native/lib/screens/example2/components/body.dart
Normal file
15
web_native/lib/screens/example2/components/body.dart
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class Body extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Center(
|
||||||
|
child: RaisedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: Text('Go back!'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
20
web_native/lib/screens/example2/example2-bloc.dart
Normal file
20
web_native/lib/screens/example2/example2-bloc.dart
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:ui';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:imagini/models/contact.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:imagini/bloc/bloc.dart';
|
||||||
|
|
||||||
|
class Example2Bloc extends Bloc {
|
||||||
|
StreamSubscription _audioPlayerStateSubscription;
|
||||||
|
|
||||||
|
Stream<String> get example => _exampleSubject.stream;
|
||||||
|
Sink<String> get exampleSink => _exampleSubject.sink;
|
||||||
|
final StreamController<String> _exampleSubject = StreamController<String>();
|
||||||
|
|
||||||
|
Example2Bloc();
|
||||||
|
|
||||||
|
void dispose() {
|
||||||
|
_exampleSubject.close();
|
||||||
|
}
|
||||||
|
}
|
40
web_native/lib/screens/example2/examplescreen2.dart
Normal file
40
web_native/lib/screens/example2/examplescreen2.dart
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:imagini/screens/example2/components/body.dart';
|
||||||
|
import 'package:imagini/screens/example2/example2-bloc.dart';
|
||||||
|
import 'package:imagini/bloc/bloc-prov.dart';
|
||||||
|
|
||||||
|
class ExScreen2 extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_ExScreen2State createState() => _ExScreen2State();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ExScreen2State extends State<ExScreen2> {
|
||||||
|
Example2Bloc example2Bloc;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
example2Bloc = Example2Bloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
example2Bloc.dispose();
|
||||||
|
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider(
|
||||||
|
bloc: Example2Bloc(),
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text("Second Screen"),
|
||||||
|
),
|
||||||
|
body: Body(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
11
web_native/lib/services/exampleapi.dart
Normal file
11
web_native/lib/services/exampleapi.dart
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
|
Future<String> exampleApi(String orgid) async {
|
||||||
|
http.Response response = await http.get(
|
||||||
|
Uri.encodeFull("https://www.example.com/api"),
|
||||||
|
);
|
||||||
|
print("Respone ${response.body.toString()}");
|
||||||
|
//Returns 'true' or 'false' as a String
|
||||||
|
return response.body;
|
||||||
|
}
|
13
web_native/lib/theme/style.dart
Normal file
13
web_native/lib/theme/style.dart
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
ThemeData appTheme() {
|
||||||
|
return ThemeData(
|
||||||
|
primaryColor: Colors.white,
|
||||||
|
accentColor: Colors.orange,
|
||||||
|
hintColor: Colors.white,
|
||||||
|
dividerColor: Colors.white,
|
||||||
|
buttonColor: Colors.white,
|
||||||
|
scaffoldBackgroundColor: Colors.black,
|
||||||
|
canvasColor: Colors.black,
|
||||||
|
);
|
||||||
|
}
|
@ -1,153 +1,385 @@
|
|||||||
# Generated by pub
|
# Generated by pub
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
packages:
|
packages:
|
||||||
|
_fe_analyzer_shared:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: _fe_analyzer_shared
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "12.0.0"
|
||||||
|
analyzer:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: analyzer
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.40.6"
|
||||||
|
archive:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: archive
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.13"
|
||||||
|
args:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: args
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.6.0"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: async
|
name: async
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.5.0-nullsafety.1"
|
version: "2.5.0-nullsafety.3"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: boolean_selector
|
name: boolean_selector
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0-nullsafety.1"
|
version: "2.1.0-nullsafety.3"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: characters
|
name: characters
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0-nullsafety.3"
|
version: "1.1.0-nullsafety.5"
|
||||||
charcode:
|
charcode:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: charcode
|
name: charcode
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0-nullsafety.1"
|
version: "1.2.0-nullsafety.3"
|
||||||
|
cli_util:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cli_util
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.0"
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: clock
|
name: clock
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0-nullsafety.1"
|
version: "1.1.0-nullsafety.3"
|
||||||
collection:
|
collection:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: collection
|
name: collection
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.15.0-nullsafety.3"
|
version: "1.15.0-nullsafety.5"
|
||||||
|
convert:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: convert
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.1"
|
||||||
|
coverage:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: coverage
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.14.2"
|
||||||
|
crypto:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: crypto
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.5"
|
||||||
cupertino_icons:
|
cupertino_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: cupertino_icons
|
name: cupertino_icons
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.2"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: fake_async
|
name: fake_async
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0-nullsafety.1"
|
version: "1.2.0-nullsafety.3"
|
||||||
|
file:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: file
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "6.0.0-nullsafety.4"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_driver:
|
||||||
|
dependency: transitive
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
fuchsia_remote_debug_protocol:
|
||||||
|
dependency: transitive
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
|
glob:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: glob
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.0"
|
||||||
|
integration_test:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.9.2+2"
|
||||||
|
io:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: io
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.4"
|
||||||
|
js:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: js
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.3-nullsafety.3"
|
||||||
|
json_rpc_2:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: json_rpc_2
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.2"
|
||||||
|
logging:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: logging
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.11.4"
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: matcher
|
name: matcher
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.10-nullsafety.1"
|
version: "0.12.10-nullsafety.3"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0-nullsafety.3"
|
version: "1.3.0-nullsafety.6"
|
||||||
|
node_interop:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: node_interop
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.1"
|
||||||
|
node_io:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: node_io
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.1"
|
||||||
|
package_config:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: package_config
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.9.3"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path
|
name: path
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.0-nullsafety.1"
|
version: "1.8.0-nullsafety.3"
|
||||||
|
pedantic:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pedantic
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.10.0-nullsafety.3"
|
||||||
|
platform:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: platform
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.0-nullsafety.4"
|
||||||
|
pool:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pool
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.5.0-nullsafety.3"
|
||||||
|
process:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: process
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "4.0.0-nullsafety.4"
|
||||||
|
pub_semver:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pub_semver
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.4"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.99"
|
version: "0.0.99"
|
||||||
|
source_map_stack_trace:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: source_map_stack_trace
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0-nullsafety.4"
|
||||||
|
source_maps:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: source_maps
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.10.10-nullsafety.3"
|
||||||
source_span:
|
source_span:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: source_span
|
name: source_span
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.0-nullsafety.2"
|
version: "1.8.0-nullsafety.4"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: stack_trace
|
name: stack_trace
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.10.0-nullsafety.1"
|
version: "1.10.0-nullsafety.6"
|
||||||
stream_channel:
|
stream_channel:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: stream_channel
|
name: stream_channel
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0-nullsafety.1"
|
version: "2.1.0-nullsafety.3"
|
||||||
string_scanner:
|
string_scanner:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: string_scanner
|
name: string_scanner
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0-nullsafety.1"
|
version: "1.1.0-nullsafety.3"
|
||||||
|
sync_http:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sync_http
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.0"
|
||||||
term_glyph:
|
term_glyph:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: term_glyph
|
name: term_glyph
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0-nullsafety.1"
|
version: "1.2.0-nullsafety.3"
|
||||||
test_api:
|
test_api:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.19-nullsafety.2"
|
version: "0.2.19-nullsafety.6"
|
||||||
|
test_core:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: test_core
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.12-nullsafety.9"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: typed_data
|
name: typed_data
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0-nullsafety.3"
|
version: "1.3.0-nullsafety.5"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_math
|
name: vector_math
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0-nullsafety.3"
|
version: "2.1.0-nullsafety.5"
|
||||||
|
vm_service:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: vm_service
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "5.5.0"
|
||||||
|
watcher:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: watcher
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.9.7+15"
|
||||||
|
web_socket_channel:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web_socket_channel
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
|
webdriver:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: webdriver
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.2"
|
||||||
|
yaml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: yaml
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.1"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.10.0-110 <2.11.0"
|
dart: ">=2.12.0-0.0 <3.0.0"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
name: Imagini
|
name: imagini
|
||||||
description: A new Flutter project.
|
description: A new Flutter project.
|
||||||
|
|
||||||
# The following line prevents the package from being accidentally published to
|
# The following line prevents the package from being accidentally published to
|
||||||
@ -27,11 +27,13 @@ dependencies:
|
|||||||
|
|
||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
cupertino_icons: ^1.0.0
|
cupertino_icons: ^1.0.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
integration_test:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
import 'package:web_native/main.dart';
|
import 'package:imagini/main.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||||
|
BIN
web_native/web/favicon.png
Normal file
BIN
web_native/web/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 917 B |
BIN
web_native/web/icons/Icon-192.png
Normal file
BIN
web_native/web/icons/Icon-192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
BIN
web_native/web/icons/Icon-512.png
Normal file
BIN
web_native/web/icons/Icon-512.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.1 KiB |
45
web_native/web/index.html
Normal file
45
web_native/web/index.html
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<!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.
|
||||||
|
|
||||||
|
Fore more details:
|
||||||
|
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
|
||||||
|
-->
|
||||||
|
<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="apple-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="imagini">
|
||||||
|
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
||||||
|
|
||||||
|
<!-- Favicon -->
|
||||||
|
<link rel="icon" type="image/png" href="favicon.png"/>
|
||||||
|
|
||||||
|
<title>imagini</title>
|
||||||
|
<link rel="manifest" href="manifest.json">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- This script installs service_worker.js to provide PWA functionality to
|
||||||
|
application. For more information, see:
|
||||||
|
https://developers.google.com/web/fundamentals/primers/service-workers -->
|
||||||
|
<script>
|
||||||
|
if ('serviceWorker' in navigator) {
|
||||||
|
window.addEventListener('flutter-first-frame', function () {
|
||||||
|
navigator.serviceWorker.register('flutter_service_worker.js');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script src="main.dart.js" type="application/javascript"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
23
web_native/web/manifest.json
Normal file
23
web_native/web/manifest.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "imagini",
|
||||||
|
"short_name": "imagini",
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Reference in New Issue
Block a user