diff --git a/boss_app2/.gitignore b/boss_app2/.gitignore new file mode 100644 index 0000000..0fa6b67 --- /dev/null +++ b/boss_app2/.gitignore @@ -0,0 +1,46 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Web related +lib/generated_plugin_registrant.dart + +# 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 diff --git a/boss_app2/.metadata b/boss_app2/.metadata new file mode 100644 index 0000000..e8dca9f --- /dev/null +++ b/boss_app2/.metadata @@ -0,0 +1,10 @@ +# 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: 73adb1406a9cff796e2203ad16fd285220a6ec97 + channel: beta + +project_type: app diff --git a/boss_app2/README.md b/boss_app2/README.md new file mode 100644 index 0000000..7b56fea --- /dev/null +++ b/boss_app2/README.md @@ -0,0 +1,16 @@ +# boss_app2 + +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://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/boss_app2/analysis_options.yaml b/boss_app2/analysis_options.yaml new file mode 100644 index 0000000..acce3bf --- /dev/null +++ b/boss_app2/analysis_options.yaml @@ -0,0 +1,921 @@ +## +# Lint rules to be used for apps without developer facing API. i.e. command line tools and Flutter applications +## +analyzer: + strong-mode: + # Will become the default once non-nullable types land + # https://github.com/dart-lang/sdk/issues/31410#issuecomment-510683629 + implicit-casts: true + implicit-dynamic: true + errors: + # treat missing required parameters as a warning (not a hint) + missing_required_param: warning + # treat missing returns as a warning (not a hint) + missing_return: warning + # allow having TODOs in the code + todo: info + +# Rules are in the same order (alphabetically) as documented at http://dart-lang.github.io/linter/lints +# and https://github.com/dart-lang/linter/blob/master/example/all.yaml +linter: + rules: + # Prevents accidental return type changes which results in a breaking API change. + # Enforcing return type makes API changes visible in a diff + # pedantic: enabled + # http://dart-lang.github.io/linter/lints/always_declare_return_types.html + - always_declare_return_types + + # Single line `if`s are fine as recommended in Effective Dart "DO format your code using dartfmt" + # pedantic: disabled + # http://dart-lang.github.io/linter/lints/always_put_control_body_on_new_line.html + # - always_put_control_body_on_new_line + + # Flutter widgets always put a Key as first optional parameter which breaks this rule. + # Also violates other orderings like matching the class fields or alphabetically. + # pedantic: disabled + # http://dart-lang.github.io/linter/lints/always_declare_return_types.html + # - always_put_required_named_parameters_first + + # All non nullable named parameters should be and annotated with @required. + # This allows API consumers to get warnings via lint rather than a crash a runtime. + # Might become obsolete with Non-Nullable types + # pedantic: enabled + # http://dart-lang.github.io/linter/lints/always_require_non_null_named_parameters.html + - always_require_non_null_named_parameters + + # Since dart 2.0 dart is a sound language, specifying types is not required anymore. + # `var foo = 10;` is enough information for the compiler to make foo a int. + # Violates Effective Dart "AVOID type annotating initialized local variables". + # Makes code unnecessarily complex https://github.com/dart-lang/linter/issues/1620 + # pedantic: disabled + # http://dart-lang.github.io/linter/lints/always_specify_types.html + # - always_specify_types + + # Protect against unintentionally overriding superclass members + # pedantic: enabled + # http://dart-lang.github.io/linter/lints/annotate_overrides.html + - annotate_overrides + + # All methods should define a return type. dynamic is no exception. + # Violates Effective Dart "PREFER annotating with dynamic instead of letting inference fail" + # pedantic: disabled + # http://dart-lang.github.io/linter/lints/avoid_annotating_with_dynamic.html + # - avoid_annotating_with_dynamic + + # A leftover from dart1, should be deprecated + # pedantic: disabled + # - https://github.com/dart-lang/linter/issues/1401 + # http://dart-lang.github.io/linter/lints/avoid_as.html + # - avoid_as + + # Highlights boolean expressions which can be simplified + # http://dart-lang.github.io/linter/lints/avoid_bool_literals_in_conditional_expressions.html + - avoid_bool_literals_in_conditional_expressions + + # There are no strong arguments to enable this rule because it is very strict. Catching anything is useful + # and common even if not always the most correct thing to do. + # pedantic: disabled + # http://dart-lang.github.io/linter/lints/avoid_catches_without_on_clauses.html + # - avoid_catches_without_on_clauses + + # Errors aren't for catching but to prevent prior to runtime + # pedantic: disabled + # http://dart-lang.github.io/linter/lints/avoid_catching_errors.html + - avoid_catching_errors + + # Can usually be replaced with an extension + # pedantic: disabled + # http://dart-lang.github.io/linter/lints/avoid_classes_with_only_static_members.html + - avoid_classes_with_only_static_members + + # Never accidentally use dynamic invocations + # Dart SDK: unreleased • (Linter vnull) + # https://dart-lang.github.io/linter/lints/avoid_dynamic_calls.html + # avoid_dynamic_calls + + # Only useful when targeting JS + # pedantic: disabled + # http://dart-lang.github.io/linter/lints/avoid_double_and_int_checks.html + # - avoid_double_and_int_checks + + # Prevents accidental empty else cases. See samples in documentation + # pedantic: enabled + # http://dart-lang.github.io/linter/lints/avoid_empty_else.html + - avoid_empty_else + + # It is expected that mutable objects which override hash & equals shouldn't be used as keys for hashmaps. + # This one use case doesn't make all hash & equals implementations for mutable classes bad. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/avoid_equals_and_hash_code_on_mutable_classes.html + # - avoid_equals_and_hash_code_on_mutable_classes + + # Use different quotes instead of escaping + # Dart SDK: >= 2.8.0-dev.11.0 • (Linter v0.1.111) + # https://dart-lang.github.io/linter/lints/avoid_escaping_inner_quotes.html + - avoid_escaping_inner_quotes + + # Prevents unnecessary allocation of a field + # pedantic: disabled + # http://dart-lang.github.io/linter/lints/avoid_field_initializers_in_const_classes.html + - avoid_field_initializers_in_const_classes + + # Prevents allocating a lambda and allows return/break/continue control flow statements inside the loop + # http://dart-lang.github.io/linter/lints/avoid_function_literals_in_foreach_calls.html + - avoid_function_literals_in_foreach_calls + + # Don't break value types by implementing them + # http://dart-lang.github.io/linter/lints/avoid_implementing_value_types.html + - avoid_implementing_value_types + + # Removes redundant `= null;` + # https://dart-lang.github.io/linter/lints/avoid_init_to_null.html + - avoid_init_to_null + + # Only useful when targeting JS + # Warns about too large integers when compiling to JS + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/avoid_js_rounded_ints.html + # - avoid_js_rounded_ints + + # Null checks aren't required in ==() operators + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/avoid_null_checks_in_equality_operators.html + - avoid_null_checks_in_equality_operators + + # Good APIs don't use ambiguous boolean parameters. Instead use named parameters + # https://dart-lang.github.io/linter/lints/avoid_positional_boolean_parameters.html + - avoid_positional_boolean_parameters + + # Don't call print in production code + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/avoid_print.html + # - avoid_print + + # Always prefer function references over typedefs. + # Jumping twice in code to see the signature of a lambda sucks. This is different from the flutter analysis_options + # https://dart-lang.github.io/linter/lints/avoid_private_typedef_functions.html + - avoid_private_typedef_functions + + # Don't explicitly set defaults + # Dart SDK: >= 2.8.0-dev.1.0 • (Linter v0.1.107) + # https://dart-lang.github.io/linter/lints/avoid_redundant_argument_values.html + - avoid_redundant_argument_values + + # package or relative? Let's end the discussion and use package everywhere. + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/avoid_relative_lib_imports.html + - avoid_relative_lib_imports + + # Not recommended to break dartdoc but besides that there is no reason to continue with bad naming + # https://dart-lang.github.io/linter/lints/avoid_renaming_method_parameters.html + # - avoid_renaming_method_parameters + + # Setters always return void, therefore defining void is redundant + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/avoid_return_types_on_setters.html + - avoid_return_types_on_setters + + # Especially with Non-Nullable types on the horizon, `int?` is fine. + # There are plenty of valid reasons to return null. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/avoid_returning_null.html + # - avoid_returning_null + + # Don't use `Future?`, therefore never return null instead of a Future. + # Will become obsolete one Non-Nullable types land + # https://dart-lang.github.io/linter/lints/avoid_returning_null_for_future.html + - avoid_returning_null_for_future + + # Use empty returns, don't show off with you knowledge about dart internals. + # https://dart-lang.github.io/linter/lints/avoid_returning_null_for_void.html + - avoid_returning_null_for_void + + # Hinting you forgot about the cascade operator. But too often you did this on purpose. + # There are plenty of valid reasons to return this. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/avoid_returning_this.html + # - avoid_returning_this + + # Prevents logical inconsistencies. It's good practice to define getters for all existing setters. + # https://dart-lang.github.io/linter/lints/avoid_setters_without_getters.html + - avoid_setters_without_getters + + # Don't reuse a type parameter when on with the same name already exists in the same scope + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/avoid_shadowing_type_parameters.html + - avoid_shadowing_type_parameters + + # A single cascade operator can be replaced with a normal method call + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/avoid_single_cascade_in_expression_statements.html + - avoid_single_cascade_in_expression_statements + + # Might cause frame drops because of synchronous file access on mobile, especially on older phones with slow storage. + # There are no known measurements sync access does *not* drop frames. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/avoid_slow_async_io.html + # - avoid_slow_async_io + + # Don't use .toString() in production code which might be minified + # Dart SDK: >= 2.10.0-144.0.dev • (Linter v0.1.119) + # https://dart-lang.github.io/linter/lints/avoid_type_to_string.html + - avoid_type_to_string + + # Don't use a parameter names which can be confused with a types (i.e. int, bool, num, ...) + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/avoid_types_as_parameter_names.html + - avoid_types_as_parameter_names + + # Adding the type is not required, but sometimes improves readability. Therefore removing it doesn't always help + # https://dart-lang.github.io/linter/lints/avoid_types_on_closure_parameters.html + # - avoid_types_on_closure_parameters + + # Containers without parameters have no effect and can be removed + # https://dart-lang.github.io/linter/lints/avoid_unnecessary_containers.html + - avoid_unnecessary_containers + + # Unused parameters should be removed + # https://dart-lang.github.io/linter/lints/avoid_unused_constructor_parameters.html + - avoid_unused_constructor_parameters + + # TODO double check + # For async functions use `Future` as return value, not `void` + # This allows usage of the await keyword and prevents operations from running in parallel. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/avoid_void_async.html + - avoid_void_async + + # Flutter mobile only: Web packages aren't available in mobile flutter apps + # https://dart-lang.github.io/linter/lints/avoid_web_libraries_in_flutter.html + - avoid_web_libraries_in_flutter + + # Use the await keyword only for futures. There is nothing to await in synchronous code + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/await_only_futures.html + - await_only_futures + + # Follow the style guide and use UpperCamelCase for extensions + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/camel_case_extensions.html + - camel_case_extensions + + # Follow the style guide and use UpperCamelCase for class names and typedefs + # https://dart-lang.github.io/linter/lints/camel_case_types.html + - camel_case_types + + # Prevents leaks and code executing after their lifecycle. + # Discussion https://github.com/passsy/dart-lint/issues/4 + # + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/cancel_subscriptions.html + - cancel_subscriptions + + # The cascade syntax is weird and you shouldn't be forced to use it. + # False positives: + # https://github.com/dart-lang/linter/issues/1589 + # + # https://dart-lang.github.io/linter/lints/cascade_invocations.html + # - cascade_invocations + + # Don't cast T? to T. Use ! instead + # Dart SDK: >= 2.11.0-182.0.dev • (Linter v0.1.120) + # https://dart-lang.github.io/linter/lints/cast_nullable_to_non_nullable.html + - cast_nullable_to_non_nullable + + # False positives, not reliable enough + # - https://github.com/dart-lang/linter/issues/1381 + # + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/close_sinks.html + # - close_sinks + + # False positives: + # - https://github.com/dart-lang/linter/issues/1142 + # + # https://dart-lang.github.io/linter/lints/comment_references.html + # - comment_references + + # Follow standard dart naming style. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/constant_identifier_names.html + - constant_identifier_names + + # Prevents hard to debug code + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/control_flow_in_finally.html + - control_flow_in_finally + + # Single line `if`s are fine, but when a new line splits the bool expression and body curly braces + # are recommended. It prevents the danging else problem and easily allows the addition of more lines inside + # the if body + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/curly_braces_in_flow_control_structures.html + - curly_braces_in_flow_control_structures + + # Still experimental and pretty much work when enforced + # https://dart-lang.github.io/linter/lints/diagnostic_describe_all_properties.html + # - diagnostic_describe_all_properties + + # Follows dart style. Fully supported by IDEs and no manual effort for a consistent style + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/directives_ordering.html + - directives_ordering + + # String.fromEnvironment looks up env variables at compile time. The variable is baked in by the compiler + # and can't be changed by environment variables. + # + # For dart apps: + # Better look up a environment variable at runtime with Platform.environment + # or use code generation to define variables at compile time. + # + # For Flutter apps: + # String.fromEnvironment is the recommended way to include variables defined with `flutter build --dart-define` + # + # pedantic: disabled + # Dart SDK: >= 2.10.0-0.0.dev • (Linter v0.1.117) + # https://dart-lang.github.io/linter/lints/do_not_use_environment.html + # - do_not_use_environment + + # Add a comment why no further error handling is required + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/empty_catches.html + - empty_catches + + # Removed empty constructor bodies + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/empty_constructor_bodies.html + - empty_constructor_bodies + + # Don't allow empty if bodies. Works together with curly_braces_in_flow_control_structures + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/empty_statements.html + - empty_statements + + # Enums aren't powerful enough, now enum like classes get the same linting support + # pedantic: disabled + # Dart SDK: >= 2.9.0-12.0.dev • (Linter v0.1.116) + # https://dart-lang.github.io/linter/lints/exhaustive_cases.html + - exhaustive_cases + + # Follow dart file naming schema + # https://dart-lang.github.io/linter/lints/file_names.html + # - file_names + + # Very flutter specific, not applicable for all projects + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/flutter_style_todos.html + # - flutter_style_todos # not all todos require a ticket + + # hashCode and equals need to be consistent. One can't live without another. + # https://dart-lang.github.io/linter/lints/hash_and_equals.html + - hash_and_equals + + # DON'T import implementation files from another package. + # If you need access to some internal code, create an issue + # https://dart-lang.github.io/linter/lints/implementation_imports.html + - implementation_imports + + # Although there are some false positives, this lint generally catches unnecessary checks + # - https://github.com/dart-lang/linter/issues/811 + # + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/invariant_booleans.html + - invariant_booleans + + # Type check for Iterable.contains(other) where other is! T + # otherwise contains will always report false. Those errors are usually very hard to catch. + # https://dart-lang.github.io/linter/lints/iterable_contains_unrelated_type.html + - iterable_contains_unrelated_type + + # Hint to join return and assignment. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/join_return_with_assignment.html + - join_return_with_assignment + + # Add leading \n which which makes multiline strings easier to read + # Dart SDK: >= 2.8.0-dev.16.0 • (Linter v0.1.113) + # https://dart-lang.github.io/linter/lints/leading_newlines_in_multiline_strings.html + - leading_newlines_in_multiline_strings + + # Makes sure a library name is a valid dart identifier. + # This comes in handy for test files combining multiple tests where the file name can be used as identifier + # + # ``` + # import src/some_test.dart as some_test; + # + # main() { + # some_test.main(); + # } + # ``` + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/library_names.html + - library_names + + # Follow dart style + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/library_prefixes.html + - library_prefixes + + # Nobody wants to manually wrap lines when changing a few words. This rule is too hard to be a "general" rule + # https://dart-lang.github.io/linter/lints/lines_longer_than_80_chars.html + # - lines_longer_than_80_chars + + # Type check for List.remove(item) where item is! T + # The list can't contain item. Those errors are not directly obvious especially when refactoring. + # https://dart-lang.github.io/linter/lints/list_remove_unrelated_type.html + - list_remove_unrelated_type + + # Good for libraries to prevent unnecessary code paths. + # False positives may occur for applications when boolean properties are generated by external programs + # producing auto-generated source code + # + # Known issue: while(true) loops https://github.com/dart-lang/linter/issues/453 + # + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/literal_only_boolean_expressions.html + # - literal_only_boolean_expressions + + # Don't forget the whitespaces at the end + # Dart SDK: >= 2.8.0-dev.10.0 • (Linter v0.1.110) + # https://dart-lang.github.io/linter/lints/missing_whitespace_between_adjacent_strings.html + - missing_whitespace_between_adjacent_strings + + # Concat Strings obviously with `+` inside a list. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/no_adjacent_strings_in_list.html + - no_adjacent_strings_in_list + + # Second case is basically dead code which will never be reached. + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/no_duplicate_case_values.html + - no_duplicate_case_values + + # Flutter only: `createState` shouldn't pass information into the state + # https://dart-lang.github.io/linter/lints/no_logic_in_create_state.html + - no_logic_in_create_state + + # calling `runtimeType` may be a performance problem + # Dart SDK: >= 2.8.0-dev.10.0 • (Linter v0.1.110) + # https://dart-lang.github.io/linter/lints/no_runtimeType_toString.html + - no_runtimeType_toString + + # Follow dart style naming conventions + # https://dart-lang.github.io/linter/lints/non_constant_identifier_names.html + - non_constant_identifier_names + + # Generic T might have a value of String or String?. Both are valid. + # This lint triggers when ! is used on T? casting (String?)? to String and not (String?)? to String? + # Dart SDK: >= 2.11.0-182.0.dev • (Linter v0.1.120) + # https://dart-lang.github.io/linter/lints/null_check_on_nullable_type_parameter.html + - null_check_on_nullable_type_parameter + + # Might become irrelevant when non-nullable types land in dart. Until then use this lint check which checks for + # non null arguments for specific dart sdk methods. + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/null_closures.html + - null_closures + + # Types for local variables may improve readability. + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/omit_local_variable_types.html + # - omit_local_variable_types + + # Defining interfaces (abstract classes), with only one method, makes sense architecture wise + # Discussion: https://github.com/passsy/dart-lint/issues/2 + # + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/one_member_abstracts.html + # - one_member_abstracts + + # Since Errors aren't intended to be caught (see avoid_catching_errors), throwing anything + # doesn't cause trouble. + # https://dart-lang.github.io/linter/lints/only_throw_errors.html + # - only_throw_errors + + # Highlights unintentionally overridden fields. + # https://dart-lang.github.io/linter/lints/overridden_fields.html + - overridden_fields + + # Only relevant for packages, not applications or general dart code + # https://dart-lang.github.io/linter/lints/package_api_docs.html + # - package_api_docs + + # Follow dart style package naming convention + # https://dart-lang.github.io/linter/lints/package_names.html + - package_names + + # Seems very rare, especially for applications. + # https://dart-lang.github.io/linter/lints/package_prefixed_library_names.html + - package_prefixed_library_names + + # Most likely a mistake, if not: bad practice + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/parameter_assignments.html + - parameter_assignments + + # Is contradictory to `no_adjacent_strings_in_list` + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/prefer_adjacent_string_concatenation.html + # - prefer_adjacent_string_concatenation + + # Makes it easier to migrate to const constructors and to have final fields + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/prefer_asserts_in_initializer_lists.html + - prefer_asserts_in_initializer_lists + + # Assertions blocks don't require a message because they throw simple to understand errors + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/prefer_asserts_with_message.html + # - prefer_asserts_with_message + + # Collection literals are shorter. They exists, use them. + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/prefer_collection_literals.html + - prefer_collection_literals + + # Use the ??= operator when possible + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/prefer_conditional_assignment.html + - prefer_conditional_assignment + + # Always use const when possible, make runtime faster + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/prefer_const_constructors.html + - prefer_const_constructors + + # Add a const constructor when possible + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/prefer_const_constructors_in_immutables.html + - prefer_const_constructors_in_immutables + + # final is good, const is better + # https://dart-lang.github.io/linter/lints/prefer_const_declarations.html + - prefer_const_declarations + + # Always use const when possible, make runtime faster + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/prefer_const_literals_to_create_immutables.html + - prefer_const_literals_to_create_immutables + + # Dart has named constructors. Static methods in other languages (java) are a workaround which don't have + # named constructors. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/prefer_constructors_over_static_methods.html + - prefer_constructors_over_static_methods + + # Contains may be faster and is easier to read + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/prefer_contains.html + - prefer_contains + + # Use whatever makes you happy. lint doesn't define a style + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/prefer_double_quotes.html + # - prefer_double_quotes + + # Prevent confusion with call-side when using named parameters + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/prefer_equal_for_default_values.html + - prefer_equal_for_default_values + + # Single line methods + implementation makes it hard to write comments for that line. + # Dense code isn't necessarily better code. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/prefer_expression_function_bodies.html + # - prefer_expression_function_bodies + + # Avoid accidental reassignments and allows the compiler to do optimizations. + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/prefer_final_fields.html + - prefer_final_fields + + # Helps avoid accidental reassignments and allows the compiler to do optimizations. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/prefer_final_in_for_each.html + - prefer_final_in_for_each + + # Helps avoid accidental reassignments and allows the compiler to do optimizations. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/prefer_final_locals.html + - prefer_final_locals + + # Saves lot of code + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/prefer_for_elements_to_map_fromIterable.html + - prefer_for_elements_to_map_fromIterable + + # Dense code isn't necessarily better code + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/prefer_foreach.html + # - prefer_foreach + + # As Dart allows local function declarations, it is a good practice to use them in the place of function literals. + # https://dart-lang.github.io/linter/lints/prefer_function_declarations_over_variables.html + - prefer_function_declarations_over_variables + + # For consistency + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/prefer_generic_function_type_aliases.html + - prefer_generic_function_type_aliases + + # Allows potential usage of const + # https://dart-lang.github.io/linter/lints/prefer_if_elements_to_conditional_expressions.html + - prefer_if_elements_to_conditional_expressions + + # Dart has a special operator for this, use it + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/prefer_if_null_operators.html + - prefer_if_null_operators + + # Terser code + # https://dart-lang.github.io/linter/lints/prefer_initializing_formals.html + - prefer_initializing_formals + + # Easier move towards const, and way easier to read + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/prefer_inlined_adds.html + - prefer_inlined_adds + + # There is no argument which makes int literals better than double literals for doubles. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/prefer_int_literals.html + # - prefer_int_literals + + # Interpolate, use less "", '' and + + # https://dart-lang.github.io/linter/lints/prefer_interpolation_to_compose_strings.html + - prefer_interpolation_to_compose_strings + + # Iterables do not necessary know their length + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/prefer_is_empty.html + - prefer_is_empty + + # Easier to read + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/prefer_is_not_empty.html + - prefer_is_not_empty + + # Use the `foo is! Foo` instead of `!(foo is Foo)` + # https://dart-lang.github.io/linter/lints/prefer_is_not_operator.html + - prefer_is_not_operator + + # Easier to read + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/prefer_iterable_whereType.html + - prefer_iterable_whereType + + # Users of a 3rd party mixins can't change 3rd party code to use the mixin syntax. + # This makes the rule useless + # https://dart-lang.github.io/linter/lints/prefer_mixin.html + # - prefer_mixin + + # Makes expressions with null checks easier to read. + # https://github.com/flutter/flutter/pull/32711#issuecomment-492930932 + - prefer_null_aware_operators + + # Conflicting with `avoid_relative_lib_imports` which is enforced + # https://dart-lang.github.io/linter/lints/prefer_relative_imports.html + # - prefer_relative_imports + + # Use whatever makes you happy. noexcuse doesn't define a style + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/prefer_single_quotes.html + # - prefer_single_quotes + + # Allows potential usage of const + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/prefer_spread_collections.html + - prefer_spread_collections + + # Define types + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/prefer_typing_uninitialized_variables.html + - prefer_typing_uninitialized_variables + + # Null is not a type, use void + # https://dart-lang.github.io/linter/lints/prefer_void_to_null.html + - prefer_void_to_null + + # Document the replacement API + # https://dart-lang.github.io/linter/lints/provide_deprecation_message.html + - provide_deprecation_message + + # Definitely not a rule for standard dart code. Maybe relevant for packages + # https://dart-lang.github.io/linter/lints/public_member_api_docs.html + # - public_member_api_docs + + # Hints accidental recursions + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/recursive_getters.html + - recursive_getters + + # Flutter only, prefer SizedBox over Container which offers a const constructors + # Dart SDK: >= 2.9.0-4.0.dev • (Linter v0.1.115) + # https://dart-lang.github.io/linter/lints/sized_box_for_whitespace.html + - sized_box_for_whitespace + + # Follow dart style use triple slashes + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/slash_for_doc_comments.html + - slash_for_doc_comments + + # Flutter only, always put child last + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/sort_child_properties_last.html + - sort_child_properties_last + + # Working, results in consistent code. But too opinionated + # Discussion: https://github.com/passsy/dart-lint/issues/1 + # + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/sort_constructors_first.html + # - sort_constructors_first + + # Any sorting is better than no sorting + # https://dart-lang.github.io/linter/lints/sort_pub_dependencies.html + # - sort_pub_dependencies + + # Default constructor comes first. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/sort_unnamed_constructors_first.html + - sort_unnamed_constructors_first + + # First test, then cast + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/test_types_in_equals.html + - test_types_in_equals + + # Hard to debug and bad style + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/throw_in_finally.html + - throw_in_finally + + # Help the compiler at compile time with non-null asserts rather than crashing at runtime + # Dart SDK: >= 2.11.0-182.0.dev • (Linter v0.1.120) + # https://dart-lang.github.io/linter/lints/tighten_type_of_initializing_formals.html + - tighten_type_of_initializing_formals + + # Type annotations make the compiler intelligent, use them + # https://dart-lang.github.io/linter/lints/type_annotate_public_apis.html + - type_annotate_public_apis + + # Don't add types for already typed constructor parameters. + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/type_init_formals.html + - type_init_formals + + # Too many false positives. + # Using the pedantic package for the unawaited function doesn't make code better readable + # + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/unawaited_futures.html + # - unawaited_futures + + # Remove async/await clutter when not required + # https://dart-lang.github.io/linter/lints/unnecessary_await_in_return.html + - unnecessary_await_in_return + + # Remove unnecessary braces + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/unnecessary_brace_in_string_interps.html + - unnecessary_brace_in_string_interps + + # Yes, const everywhere. But not in an already const scope + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/unnecessary_const.html + - unnecessary_const + + # Disabled because `final` prevents accidental reassignment + # https://dart-lang.github.io/linter/lints/unnecessary_final.html + # - unnecessary_final + + # Getter/setters can be added later on in a non API breaking manner + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/unnecessary_getters_setters.html + - unnecessary_getters_setters + + # Flutter setState is a good example where a lambda should always be used. + # https://github.com/dart-lang/linter/issues/498 + # + # Some generic code sometimes requires lambdas, otherwise the generic type isn't forwarded correctly. + # + # https://dart-lang.github.io/linter/lints/unnecessary_lambdas.html + # - unnecessary_lambdas + + # Remove the optional `new` keyword + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/unnecessary_new.html + - unnecessary_new + + # Don't assign `null` when value is already `null`. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/unnecessary_null_aware_assignments.html + - unnecessary_null_aware_assignments + + # Remove ! when already non-nullable + # Dart SDK: >= 2.10.0-144.0.dev • (Linter v0.1.119) + # https://dart-lang.github.io/linter/lints/unnecessary_null_checks.html + - unnecessary_null_checks + + # Don't assign `null` when value is already `null`. + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/unnecessary_null_in_if_null_operators.html + - unnecessary_null_in_if_null_operators + + # If a variable doesn't change and is initialized, no need to define it as nullable (NNDB) + # Dart SDK: >= 2.10.0-10.0.dev • (Linter v0.1.118) + # https://dart-lang.github.io/linter/lints/unnecessary_nullable_for_final_variable_declarations.html + - unnecessary_nullable_for_final_variable_declarations + + # Remove overrides which simply call super + # https://dart-lang.github.io/linter/lints/unnecessary_overrides.html + - unnecessary_overrides + + # Remove clutter where possible + # https://dart-lang.github.io/linter/lints/unnecessary_parenthesis.html + - unnecessary_parenthesis + + # Use raw string only when needed + # Dart SDK: >= 2.8.0-dev.11.0 • (Linter v0.1.111) + # https://dart-lang.github.io/linter/lints/unnecessary_raw_strings.html + - unnecessary_raw_strings + + # Avoid magic overloads of + operators + # https://dart-lang.github.io/linter/lints/unnecessary_statements.html + - unnecessary_statements + + # Remove unnecessary escape characters + # Dart SDK: >= 2.8.0-dev.11.0 • (Linter v0.1.111) + # https://dart-lang.github.io/linter/lints/unnecessary_string_escapes.html + - unnecessary_string_escapes + + # Completely unnecessary code, simplify to save a few CPU cycles + # Dart SDK: >= 2.8.0-dev.10.0 • (Linter v0.1.110) + # https://dart-lang.github.io/linter/lints/unnecessary_string_interpolations.html + - unnecessary_string_interpolations + + # The variable is clear, remove clutter + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/unnecessary_this.html + - unnecessary_this + + # Highlights potential bugs where unrelated types are compared with another. (always *not* equal). + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/unrelated_type_equality_checks.html + - unrelated_type_equality_checks + + # Web only + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/unsafe_html.html + - unsafe_html + + # Always use hex syntax Color(0x00000001), never Color(1) + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/use_full_hex_values_for_flutter_colors.html + - use_full_hex_values_for_flutter_colors + + # Always use generic function type syntax, don't mix styles + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/use_function_type_syntax_for_parameters.html + - use_function_type_syntax_for_parameters + + # Adding a key without using it isn't helpful in applications, only for the Flutter SDK + # Dart SDK: >= 2.8.0-dev.1.0 • (Linter v0.1.108) + # https://dart-lang.github.io/linter/lints/use_key_in_widget_constructors.html + # - use_key_in_widget_constructors + + # Some might argue late is a code smell, this lint is very opinionated. It triggers only for private fields and + # therefore might actually cleanup some code. + # There is no performance impact either way https://github.com/dart-lang/linter/pull/2189#discussion_r457945301 + # Dart SDK: >= 2.10.0-10.0.dev • (Linter v0.1.118) + # https://dart-lang.github.io/linter/lints/use_late_for_private_fields_and_variables.html + - use_late_for_private_fields_and_variables + + # Use rethrow to preserve the original stacktrace. + # https://dart.dev/guides/language/effective-dart/usage#do-use-rethrow-to-rethrow-a-caught-exception + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/use_rethrow_when_possible.html + - use_rethrow_when_possible + + # Use the setter syntax + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/use_setters_to_change_properties.html + - use_setters_to_change_properties + + # In most cases, using a string buffer is preferred for composing strings due to its improved performance. + # https://dart-lang.github.io/linter/lints/use_string_buffers.html + - use_string_buffers + + # Naming is hard, strict rules don't help + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/use_to_and_as_if_applicable.html + # - use_to_and_as_if_applicable + + # Catches invalid regular expressions. + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/valid_regexps.html + - valid_regexps + + # Don't assign anything to void + # https://dart-lang.github.io/linter/lints/void_checks.html + - void_checks diff --git a/boss_app2/android/.gitignore b/boss_app2/android/.gitignore new file mode 100644 index 0000000..6f56801 --- /dev/null +++ b/boss_app2/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/boss_app2/android/app/build.gradle b/boss_app2/android/app/build.gradle new file mode 100644 index 0000000..74b7f11 --- /dev/null +++ b/boss_app2/android/app/build.gradle @@ -0,0 +1,76 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + // compileSdkVersion flutter.compileSdkVersion + compileSdkVersion 31 + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.boss_app2" + // minSdkVersion flutter.minSdkVersion + minSdkVersion 21 + // targetSdkVersion flutter.targetSdkVersion + targetSdkVersion 31 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} + +def flutterMinSdkVersion = localProperties.getProperty('flutter.minSdkVersion') +if (flutterMinSdkVersion == null) { + flutterMinSdkVersion = flutter.minSdkVersion.toString() +} diff --git a/boss_app2/android/app/src/debug/AndroidManifest.xml b/boss_app2/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..8b9a873 --- /dev/null +++ b/boss_app2/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/boss_app2/android/app/src/main/AndroidManifest.xml b/boss_app2/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..c5c509b --- /dev/null +++ b/boss_app2/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + diff --git a/boss_app2/android/app/src/main/kotlin/com/example/boss_app2/MainActivity.kt b/boss_app2/android/app/src/main/kotlin/com/example/boss_app2/MainActivity.kt new file mode 100644 index 0000000..cb87b86 --- /dev/null +++ b/boss_app2/android/app/src/main/kotlin/com/example/boss_app2/MainActivity.kt @@ -0,0 +1,6 @@ +package com.example.boss_app2 + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/boss_app2/android/app/src/main/res/drawable-v21/launch_background.xml b/boss_app2/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/boss_app2/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/boss_app2/android/app/src/main/res/drawable/app_icon.png b/boss_app2/android/app/src/main/res/drawable/app_icon.png new file mode 100644 index 0000000..2446438 Binary files /dev/null and b/boss_app2/android/app/src/main/res/drawable/app_icon.png differ diff --git a/boss_app2/android/app/src/main/res/drawable/app_icon1.png b/boss_app2/android/app/src/main/res/drawable/app_icon1.png new file mode 100644 index 0000000..810e9ad Binary files /dev/null and b/boss_app2/android/app/src/main/res/drawable/app_icon1.png differ diff --git a/boss_app2/android/app/src/main/res/drawable/launch_background.xml b/boss_app2/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/boss_app2/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/boss_app2/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/boss_app2/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..a38de3c Binary files /dev/null and b/boss_app2/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/boss_app2/android/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_back.png b/boss_app2/android/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_back.png new file mode 100644 index 0000000..9bdbf37 Binary files /dev/null and b/boss_app2/android/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_back.png differ diff --git a/boss_app2/android/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_fore.png b/boss_app2/android/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 0000000..2446438 Binary files /dev/null and b/boss_app2/android/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_fore.png differ diff --git a/boss_app2/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/boss_app2/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..15e56f9 Binary files /dev/null and b/boss_app2/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/boss_app2/android/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_back.png b/boss_app2/android/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_back.png new file mode 100644 index 0000000..31c58b8 Binary files /dev/null and b/boss_app2/android/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_back.png differ diff --git a/boss_app2/android/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_fore.png b/boss_app2/android/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 0000000..15f5470 Binary files /dev/null and b/boss_app2/android/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_fore.png differ diff --git a/boss_app2/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/boss_app2/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..befecff Binary files /dev/null and b/boss_app2/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/boss_app2/android/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_back.png b/boss_app2/android/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_back.png new file mode 100644 index 0000000..9f108a8 Binary files /dev/null and b/boss_app2/android/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_back.png differ diff --git a/boss_app2/android/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png b/boss_app2/android/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 0000000..da77a79 Binary files /dev/null and b/boss_app2/android/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png differ diff --git a/boss_app2/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/boss_app2/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..786473f Binary files /dev/null and b/boss_app2/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/boss_app2/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png b/boss_app2/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png new file mode 100644 index 0000000..452b690 Binary files /dev/null and b/boss_app2/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png differ diff --git a/boss_app2/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png b/boss_app2/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 0000000..a34423f Binary files /dev/null and b/boss_app2/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png differ diff --git a/boss_app2/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/boss_app2/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..002cd98 Binary files /dev/null and b/boss_app2/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/boss_app2/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png b/boss_app2/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png new file mode 100644 index 0000000..1fb4828 Binary files /dev/null and b/boss_app2/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png differ diff --git a/boss_app2/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png b/boss_app2/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 0000000..b503f54 Binary files /dev/null and b/boss_app2/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png differ diff --git a/boss_app2/android/app/src/main/res/values-night/styles.xml b/boss_app2/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..3db14bb --- /dev/null +++ b/boss_app2/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/boss_app2/android/app/src/main/res/values/styles.xml b/boss_app2/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..d460d1e --- /dev/null +++ b/boss_app2/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/boss_app2/android/app/src/profile/AndroidManifest.xml b/boss_app2/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..8b9a873 --- /dev/null +++ b/boss_app2/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/boss_app2/android/build.gradle b/boss_app2/android/build.gradle new file mode 100644 index 0000000..4256f91 --- /dev/null +++ b/boss_app2/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + ext.kotlin_version = '1.6.10' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:4.1.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/boss_app2/android/gradle.properties b/boss_app2/android/gradle.properties new file mode 100644 index 0000000..94adc3a --- /dev/null +++ b/boss_app2/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/boss_app2/android/gradle/wrapper/gradle-wrapper.properties b/boss_app2/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..bc6a58a --- /dev/null +++ b/boss_app2/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip diff --git a/boss_app2/android/settings.gradle b/boss_app2/android/settings.gradle new file mode 100644 index 0000000..44e62bc --- /dev/null +++ b/boss_app2/android/settings.gradle @@ -0,0 +1,11 @@ +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/boss_app2/assets/iconnya.png b/boss_app2/assets/iconnya.png new file mode 100644 index 0000000..77a6d5e Binary files /dev/null and b/boss_app2/assets/iconnya.png differ diff --git a/boss_app2/ios/.gitignore b/boss_app2/ios/.gitignore new file mode 100644 index 0000000..7a7f987 --- /dev/null +++ b/boss_app2/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/boss_app2/ios/Flutter/AppFrameworkInfo.plist b/boss_app2/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..8d4492f --- /dev/null +++ b/boss_app2/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 9.0 + + diff --git a/boss_app2/ios/Flutter/Debug.xcconfig b/boss_app2/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/boss_app2/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/boss_app2/ios/Flutter/Release.xcconfig b/boss_app2/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/boss_app2/ios/Flutter/Release.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/boss_app2/ios/Runner.xcodeproj/project.pbxproj b/boss_app2/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..a873f10 --- /dev/null +++ b/boss_app2/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,481 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.bossApp2; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.bossApp2; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.bossApp2; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/boss_app2/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/boss_app2/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/boss_app2/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/boss_app2/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/boss_app2/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/boss_app2/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/boss_app2/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/boss_app2/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/boss_app2/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/boss_app2/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/boss_app2/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..c87d15a --- /dev/null +++ b/boss_app2/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/boss_app2/ios/Runner.xcworkspace/contents.xcworkspacedata b/boss_app2/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/boss_app2/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/boss_app2/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/boss_app2/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/boss_app2/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/boss_app2/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/boss_app2/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/boss_app2/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/boss_app2/ios/Runner/AppDelegate.swift b/boss_app2/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..9413c69 --- /dev/null +++ b/boss_app2/ios/Runner/AppDelegate.swift @@ -0,0 +1,16 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + if #available(iOS 10.0, *) { + UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate + } + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000..dc9ada4 Binary files /dev/null and b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000..28c6bf0 Binary files /dev/null and b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000..2ccbfd9 Binary files /dev/null and b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000..f091b6b Binary files /dev/null and b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000..4cde121 Binary files /dev/null and b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000..d0ef06e Binary files /dev/null and b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000..dcdc230 Binary files /dev/null and b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000..2ccbfd9 Binary files /dev/null and b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000..c8f9ed8 Binary files /dev/null and b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000..a6d6b86 Binary files /dev/null and b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000..a6d6b86 Binary files /dev/null and b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000..75b2d16 Binary files /dev/null and b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000..c4df70d Binary files /dev/null and b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000..6a84f41 Binary files /dev/null and b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000..d0e1f58 Binary files /dev/null and b/boss_app2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/boss_app2/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/boss_app2/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000..0bedcf2 --- /dev/null +++ b/boss_app2/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/boss_app2/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/boss_app2/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/boss_app2/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/boss_app2/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/boss_app2/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/boss_app2/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/boss_app2/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/boss_app2/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/boss_app2/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/boss_app2/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/boss_app2/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/boss_app2/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/boss_app2/ios/Runner/Base.lproj/LaunchScreen.storyboard b/boss_app2/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/boss_app2/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/boss_app2/ios/Runner/Base.lproj/Main.storyboard b/boss_app2/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/boss_app2/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/boss_app2/ios/Runner/Info.plist b/boss_app2/ios/Runner/Info.plist new file mode 100644 index 0000000..5feaef8 --- /dev/null +++ b/boss_app2/ios/Runner/Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Boss App2 + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + boss_app2 + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/boss_app2/ios/Runner/Runner-Bridging-Header.h b/boss_app2/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/boss_app2/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/boss_app2/lib/controller/boss_controller.dart b/boss_app2/lib/controller/boss_controller.dart new file mode 100644 index 0000000..da91552 --- /dev/null +++ b/boss_app2/lib/controller/boss_controller.dart @@ -0,0 +1,206 @@ +// ignore_for_file: non_constant_identifier_names + +import 'dart:convert'; + +import 'package:boss_app2/global.dart' as globals; +import 'package:flutter/cupertino.dart'; +// ignore: unused_import +import 'package:http/http.dart' as http; +import 'package:shared_preferences/shared_preferences.dart'; + +//create class LoginController extends ChangeNotifier +class BossController extends ChangeNotifier { + //create future string login , parameter is String username and password + Future ambilLaporan( + String tanggal, String bulan, String tahun, String filter) async { + //create string result + Map result; + + try { + final response = await http.get( + Uri.parse( + "${globals.http_to_server}api/ambil_laporan?tanggal=$tanggal&bulan=$bulan&tahun=$tahun&filter=$filter"), + headers: { + "Accept": "application/json", + "authorization": + "Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}", + "crossDomain": "true" + }); + final data = jsonDecode(response.body); + result = data; + } catch (e) { + result = {"status": "error", "message": e.toString()}; + } + + return result; + } + + Future ambilLaporanDetail(String no_log) async { + //create string result + Map result; + + try { + final response = await http.get( + Uri.parse( + "${globals.http_to_server}api/ambil_laporan_detail?no_log=$no_log"), + headers: { + "Accept": "application/json", + "authorization": + "Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}", + "crossDomain": "true" + }); + + final data = jsonDecode(response.body); + + result = data; + } catch (e) { + result = {"status": "error", "message": e.toString()}; + } + + return result; + } + + Future ambilProdukAll( + int pageNumber, String filter, String cekFilter) async { + Map result; + + try { + final response = await http.get( + Uri.parse( + "${globals.http_to_server}api/ambil_produk_all?page=$pageNumber&filter=$filter&cekfilter=$cekFilter"), + headers: { + "Accept": "application/json", + "authorization": + "Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}", + "crossDomain": "true" + }); + + final data = jsonDecode(response.body); + + result = data; + } catch (e) { + result = {"status": "error", "message": e.toString()}; + } + + return result; + } + + Future ambilLaporanProdukDetail( + int no_barang, int pageNumber, String filter, String cek_filter) async { + Map result; + + try { + final response = await http.get( + Uri.parse( + "${globals.http_to_server}api/ambil_log_produk_detail?no_barang=$no_barang&page=$pageNumber&haha=$cek_filter&filter=$filter"), + headers: { + "Accept": "application/json", + "authorization": + "Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}", + "crossDomain": "true" + }); + + final data = jsonDecode(response.body); + result = data; + } catch (e) { + result = {"status": "error", "message": e.toString()}; + } + + return result; + } + + Future ambilProdukDetail(int no_barang) async { + Map result; + + try { + final response = await http.get( + Uri.parse( + "${globals.http_to_server}api/ambil_produk_detail?no_barang=$no_barang"), + headers: { + "Accept": "application/json", + "authorization": + "Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}", + "crossDomain": "true" + }); + + final data = jsonDecode(response.body); + + result = data; + } catch (e) { + result = {"status": "error", "message": e.toString()}; + } + + return result; + } + + Future ambilLaporanAll( + int pageNumber, String filter, String cek_filter) async { + Map result; + + try { + final response = await http.get( + Uri.parse( + "${globals.http_to_server}api/ambil_laporan_all?page=$pageNumber&haha=$cek_filter&filter=$filter"), + headers: { + "Accept": "application/json", + "authorization": + "Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}", + "crossDomain": "true" + }); + + final data = jsonDecode(response.body); + result = data; + } catch (e) { + result = {"status": "error", "message": e.toString()}; + } + + return result; + } + + Future laporanRead(String no_log) async { + final sharedPreference = await SharedPreferences.getInstance(); + + // sharedPreference.remove('notif'); + try { + await http.get( + Uri.parse("${globals.http_to_server}api/laporan_read?no_log=$no_log"), + headers: { + "Accept": "application/json", + "authorization": + "Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}", + "crossDomain": "true" + }); + + // final data = jsonDecode(response.body); + final String? _notif = sharedPreference.getString('notif'); + if (_notif != null) { + final List _notifList = jsonDecode(_notif); + _notifList + .removeWhere((element) => element.toString() == no_log.toString()); + + sharedPreference.setString( + 'notif', (_notifList.isNotEmpty) ? jsonEncode(_notifList) : ""); + } + } catch (e) { + // result = {"status": "error", "message": e.toString()}; + } + } + + Future laporanReadAll() async { + final sharedPreference = await SharedPreferences.getInstance(); + + // sharedPreference.remove('notif'); + try { + await http.get(Uri.parse("${globals.http_to_server}api/laporan_read_all"), + headers: { + "Accept": "application/json", + "authorization": + "Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}", + "crossDomain": "true" + }); + sharedPreference.remove('notif'); + } catch (e) { + // result = {"status": "error", "message": e.toString()}; + } + } +} diff --git a/boss_app2/lib/controller/datatables_laporan.dart b/boss_app2/lib/controller/datatables_laporan.dart new file mode 100644 index 0000000..dbc81e3 --- /dev/null +++ b/boss_app2/lib/controller/datatables_laporan.dart @@ -0,0 +1,30 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; + +class MyData extends DataTableSource { + // Generate some made-up data + final List> _data = List.generate( + 200, + (index) => { + "id": index, + "title": "Item $index", + "price": Random().nextInt(10000), + }, + ); + + @override + bool get isRowCountApproximate => false; + @override + int get rowCount => _data.length; + @override + int get selectedRowCount => 0; + @override + DataRow getRow(int index) { + return DataRow(cells: [ + DataCell(Text(_data[index]['id'].toString())), + DataCell(Text(_data[index]["title"])), + DataCell(Text(_data[index]["price"].toString())), + ]); + } +} diff --git a/boss_app2/lib/controller/login_controller.dart b/boss_app2/lib/controller/login_controller.dart new file mode 100644 index 0000000..7cebb3f --- /dev/null +++ b/boss_app2/lib/controller/login_controller.dart @@ -0,0 +1,107 @@ +import 'dart:convert'; + +import 'package:boss_app2/global.dart' as globals; +import 'package:flutter/cupertino.dart'; +import 'package:http/http.dart' as http; +import 'package:shared_preferences/shared_preferences.dart'; + +//create class LoginController extends ChangeNotifier +class LoginController extends ChangeNotifier { + //create future string login , parameter is String username and password + Future login(String username, String password) async { + late String _returnString; + + try { + //create final sharedPreferences + final sharedPreferences = await SharedPreferences.getInstance(); + + //create http get wih basic auth + final response = await http.get( + Uri.parse( + "${globals.http_to_server}api/login_user?username=$username&password=$password"), + headers: { + "Accept": "application/json", + "authorization": + "Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}", + "crossDomain": "true" + }); + final data = jsonDecode(response.body); + if (response.statusCode == 200) { + if (data['data']['level'] == '0') { + sharedPreferences.setString('level', 'Superadmin'); + } else if (data['data']['level'] == '1') { + sharedPreferences.setString('level', 'Boss'); + } + _returnString = "1"; + sharedPreferences.setString('data', jsonEncode(data['data'])); + } else if (response.statusCode == 401) { + _returnString = "2"; + } + } catch (e) { + _returnString = "3"; + } + + //return result + return _returnString; + } + + Future getNotif() async { + int result; + final sharedPreferences = await SharedPreferences.getInstance(); + try { + final response = await http + .get(Uri.parse("${globals.http_to_server}api/cek_datanya"), headers: { + "Accept": "application/json", + "authorization": + "Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}", + "crossDomain": "true" + }); + final data = jsonDecode(response.body); + final List datanya = data['data']; + + final String? _notif = sharedPreferences.getString('notif'); + List _arrayNotif; + if (_notif == null) { + _arrayNotif = []; + } else { + _arrayNotif = jsonDecode(_notif); + } + + int jumlah = datanya.length; + bool cek = false; + + for (var i = 0; i < datanya.length; i++) { + cek = false; + for (var j = 0; j < _arrayNotif.length; j++) { + if (_arrayNotif[j].toString() == datanya[i]['no_log'].toString()) { + jumlah = jumlah - 1; + cek = true; + break; + } + } + + if (cek == false) { + _arrayNotif.add(int.parse(datanya[i]['no_log'])); + } + cek = false; + } + + sharedPreferences.setString('notif', jsonEncode(_arrayNotif)); + // // if (jumlah > 0) { + // // NotificationApi.showNotification( + // // title: 'Laporan Baru', + // // body: 'Ada $jumlah laporan baru', + // // payload: 'Laporan Baru', + // // ); + // // } + + result = jumlah; + // result = datanya; + } catch (e) { + // result = []; + result = 0; + } + + return result; + } +} diff --git a/boss_app2/lib/controller/notification_api.dart b/boss_app2/lib/controller/notification_api.dart new file mode 100644 index 0000000..36b6b7d --- /dev/null +++ b/boss_app2/lib/controller/notification_api.dart @@ -0,0 +1,98 @@ +import 'package:boss_app2/page/login.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:flutter_native_timezone/flutter_native_timezone.dart'; +import 'package:rxdart/rxdart.dart'; +import 'package:timezone/timezone.dart' as tz; +// import 'package:timezone/tzdata.dart' as tz; + +// ignore: avoid_classes_with_only_static_members +class NotificationApi { + // Below is the code for initializing the plugin using var _notificationPlugin + static final _notifications = FlutterLocalNotificationsPlugin(); + static final onNotifications = BehaviorSubject(); + + static Future showNotification({ + int id = 0, + String? title, + String? body, + String? payload, + }) async => + _notifications.show( + id, + title, + body, + await _notificanDetails(), + payload: payload, + ); + + static Future showScheduleNotification() async => + _notifications.zonedSchedule( + 0, + 'Cek Laporan', + "Laporan Baru Mungkin Ada, Sila Cek Di Aplikasi", + // tz.TZDateTime.from(scheduledDate, tz.local), + _scheduleDaily(const Time(18)), + await _notificanDetails(), + payload: "Laporan Baru Mungkin Ada, Sila Cek Di Aplikasi", + androidAllowWhileIdle: true, + uiLocalNotificationDateInterpretation: + UILocalNotificationDateInterpretation.absoluteTime, + matchDateTimeComponents: DateTimeComponents.time, + ); + + static Future _notificanDetails() async { + const AndroidNotificationDetails androidPlatformChannelSpecifics = + AndroidNotificationDetails( + 'your channel id', + 'your channel name', + channelDescription: 'your channel description', + importance: Importance.max, + // priority: Priority.high, + // ticker: 'ticker', + ); + return const NotificationDetails( + android: androidPlatformChannelSpecifics, + iOS: IOSNotificationDetails(), + ); + } + + static Future init( + {bool initScheduled = false, BuildContext? context}) async { + const android = AndroidInitializationSettings('app_icon'); + const iOS = IOSInitializationSettings(); + const settings = InitializationSettings(android: android, iOS: iOS); + + final details = await _notifications.getNotificationAppLaunchDetails(); + if (details != null && details.didNotificationLaunchApp) { + onNotifications.add(details.payload); + } + + await _notifications.initialize( + settings, + onSelectNotification: (payload) async { + Navigator.push( + context!, + MaterialPageRoute(builder: (context) => Login()), + ); + }, + ); + + if (initScheduled) { + final locationName = await FlutterNativeTimezone.getLocalTimezone(); + tz.setLocalLocation(tz.getLocation(locationName)); + } + } + + static tz.TZDateTime _scheduleDaily(Time time) { + final tz.TZDateTime now = tz.TZDateTime.now(tz.local); + final scheduledDate = tz.TZDateTime(tz.local, now.year, now.month, now.day, + time.hour, time.minute, time.second); + // if (scheduledDate.isBefore(now)) { + // scheduledDate = scheduledDate.add(const Duration(days: 1)); + // } + return scheduledDate.isBefore(now) + ? scheduledDate.add(const Duration(days: 1)) + : scheduledDate; + } +} diff --git a/boss_app2/lib/global.dart b/boss_app2/lib/global.dart new file mode 100644 index 0000000..8901aa2 --- /dev/null +++ b/boss_app2/lib/global.dart @@ -0,0 +1,3 @@ +int inidia = 1; +// ignore: non_constant_identifier_names +String http_to_server = "http://192.168.43.125/ilham/server2/"; diff --git a/boss_app2/lib/main.dart b/boss_app2/lib/main.dart new file mode 100644 index 0000000..625b6fd --- /dev/null +++ b/boss_app2/lib/main.dart @@ -0,0 +1,45 @@ +import 'package:boss_app2/controller/login_controller.dart'; +// import 'package:boss_app/controller/notification_api.dart'; +import 'package:boss_app2/page/login.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:timezone/data/latest.dart' as tz; + +import 'controller/boss_controller.dart'; + +Future main() async { + WidgetsFlutterBinding.ensureInitialized(); + tz.initializeTimeZones(); + // final locationName = await FlutterNativeTimezone.getLocalTimezone(); + // tz.setLocalLocation(tz.getLocation(locationName)); + // tz.initializeTimeZones(); + + // NotificationApi().initNotification(); + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + return MultiProvider( + providers: [ + ChangeNotifierProvider( + create: (BuildContext context) => LoginController()), + ChangeNotifierProvider( + create: (BuildContext context) => BossController()), + ], + child: MaterialApp( + title: 'Flutter Demo', + debugShowCheckedModeBanner: false, + theme: ThemeData( + primarySwatch: Colors.blue, + ), + home: Login(), + // home: const notif, + ), + ); + } +} diff --git a/boss_app2/lib/page/before_login.dart b/boss_app2/lib/page/before_login.dart new file mode 100644 index 0000000..b91d583 --- /dev/null +++ b/boss_app2/lib/page/before_login.dart @@ -0,0 +1,74 @@ +// ignore_for_file: avoid_void_async + +// import 'package:boss_app/page/boss/index.dart'; +// import 'package:boss_app/page/login.dart'; +// import 'package:boss_app/page/superadmin/index.dart'; +import 'package:boss_app2/page/boss/index.dart'; +import 'package:boss_app2/page/login.dart'; +import 'package:boss_app2/page/superadmin/index.dart'; +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class BeforeLogin extends StatefulWidget { + const BeforeLogin({Key? key}) : super(key: key); + + @override + _BeforeLoginState createState() => _BeforeLoginState(); +} + +class _BeforeLoginState extends State { + //shared prefs + late SharedPreferences sharedPreferences; + int _loading = 0; + + @override + void didChangeDependencies() async { + super.didChangeDependencies(); + sharedPreferences = await SharedPreferences.getInstance(); + final level = sharedPreferences.getString('level'); + + if (level == null) { + sharedPreferences.remove('level'); + sharedPreferences.remove('data'); + setState(() { + _loading = 3; + }); + } + if (level == 'Superadmin') { + setState(() { + _loading = 1; + }); + } + if (level == 'Boss') { + setState(() { + _loading = 2; + }); + } + } + + @override + Widget build(BuildContext context) { + late Widget retVal; + switch (_loading) { + case 0: + retVal = Scaffold( + appBar: AppBar( + title: const Text("Loading"), + ), + body: const Center(child: CircularProgressIndicator()), + ); + break; + case 1: + retVal = const SuperadminIndex(); + break; + case 2: + retVal = BossIndex(); + break; + case 3: + retVal = Login(); + break; + } + + return retVal; + } +} diff --git a/boss_app2/lib/page/boss/homeAdmin.dart b/boss_app2/lib/page/boss/homeAdmin.dart new file mode 100644 index 0000000..37cb433 --- /dev/null +++ b/boss_app2/lib/page/boss/homeAdmin.dart @@ -0,0 +1,717 @@ +// ignore_for_file: unused_element, non_constant_identifier_names +import 'dart:convert'; +import 'package:boss_app2/controller/boss_controller.dart'; +import 'package:boss_app2/widgets/ourContainer.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:month_picker_dialog/month_picker_dialog.dart'; +import 'package:provider/provider.dart'; + +class HomeAdmin extends StatefulWidget { + @override + _HomeAdminState createState() => _HomeAdminState(); +} + +class _HomeAdminState extends State { + int _year = DateTime.now().year.toInt(); + int _bulan = 0; + String _hintTextBulanTahun = '-Pilih Bulan / Tahun Terlebih Dahulu'; + + //create string tanggal from today + // ignore: prefer_final_fields + String _tanggal = + '${DateTime.now().year}-${DateTime.now().month}-${DateTime.now().day}'; + // ignore: prefer_final_fields, prefer_interpolation_to_compose_strings + String _headerLaporan = "Laporan Tanggal " + + DateTime.now().year.toString() + + '-' + + DateTime.now().month.toString() + + '-' + + DateTime.now().day.toString(); + + //create list map with field waktu, status, dan ket and push 10 random data + // List> _listLaporan = []; + + late List> _laporan; + // late List> _laporanDetail; + int _loadingLaporan = 0; + + // ignore: avoid_void_async + void _ambilLaporan(String tanggal, String bulan, String tahun, String filter, + BuildContext context) async { + final BossController _ambilLaporan = + Provider.of(context, listen: false); + + setState(() { + _loadingLaporan = 0; + }); + try { + final Map _data = + await _ambilLaporan.ambilLaporan(tanggal, bulan, tahun, filter); + // Navigator.pop(context); + + if (_data['status'] == 'success') { + //loop the _data['data'] and push to _laporan by field waktu, status, dan ket + if (_data['data'].length > 0) { + _laporan = >[]; + for (int i = 0; i < _data['data'].length; i++) { + _laporan.add({ + 'waktu': _data['data'][i]['waktu'].toString(), + 'status': _data['data'][i]['status'], + 'ket': _data['data'][i]['ket'].toString(), + 'no_log': _data['data'][i]['no_log'].toString(), + }); + } + _laporan = _laporan; + setState(() { + _loadingLaporan = 1; + }); + } else { + setState(() { + _loadingLaporan = 2; + }); + } + } else if (_data['status'] == 'error') { + setState(() { + _loadingLaporan = 3; + }); + } + } catch (e) { + setState(() { + _loadingLaporan = 3; + }); + } + } + + int _loadingBottomSheet = 0; + // ignore: avoid_void_async + void _ambilLaporanDetail(String no_log, BuildContext context) async { + final BossController _ambilLaporan = + Provider.of(context, listen: false); + + // ignore: prefer_final_locals + Map _result = {'data': 0}; + + setState(() { + _loadingBottomSheet = 0; + + _bottomSheetModal(context, _result); + }); + + try { + final Map _data = await _ambilLaporan.ambilLaporanDetail(no_log); + await _ambilLaporan.laporanRead(no_log); + Navigator.pop(context); + if (_data['status'] == 'success') { + setState(() { + _loadingBottomSheet = 1; + _bottomSheetModal(context, _data['data'][0]); + }); + } else if (_data['status'] == 'error') { + setState(() { + _loadingBottomSheet = 2; + + _bottomSheetModal(context, _result); + }); + } + } catch (e) { + setState(() { + _loadingBottomSheet = 2; + _bottomSheetModal(context, _result); + }); + } + } + + Future _bottomSheetModal( + BuildContext context, Map _result) async { + return showModalBottomSheet( + isScrollControlled: true, + context: context, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + builder: (context) => SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: (_loadingBottomSheet == 0 || _loadingBottomSheet == 2) + ? 50 + : 20, + ), + if (_loadingBottomSheet == 0) + const Center( + child: CircularProgressIndicator(), + ) + else if (_loadingBottomSheet == 1) + Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Row( + children: [ + SizedBox( + width: (MediaQuery.of(context).size.width - + (MediaQuery.of(context).size.width * 0.8)) / + 2, + ), + const Text( + 'Detail Laporan', + style: TextStyle(fontWeight: FontWeight.bold), + ), + ], + ), + ), + const SizedBox( + height: 10, + ), + _detailLaporan(_result), + ], + ) + else if (_loadingBottomSheet == 2) + const Text( + 'Koneksi Ke Server Bermasalah, Sila Periksa Jaringan Anda'), + if (_loadingBottomSheet == 0 || _loadingBottomSheet == 2) + const SizedBox( + height: 50, + ) + else if (_loadingBottomSheet == 1) + const SizedBox( + height: 30, + ), + ], + ), + ), + ); + } + + Widget _detailLaporan(Map _result) { + FocusManager.instance.primaryFocus?.unfocus(); + final Map _ket = jsonDecode(_result['ket']); + // ignore: prefer_typing_uninitialized_variables + var _detail; + final formatter = NumberFormat('#,000'); + + if (_result['status'] == 'Penjualan Produk') { + //create var list map + final List> _arrayPenjualan = (_ket['ket'] as List) + .map((dynamic item) => item as Map) + .toList(); + + final _widgetTabel = DataTable( + columns: const [ + DataColumn( + label: Text('Kode Barang'), + ), + DataColumn( + label: Text('Jumlah'), + ), + DataColumn( + label: Text('Harga Jual'), + ), + DataColumn( + label: Text('Total'), + ), + DataColumn( + label: Text('Stok Sebelumnya'), + ), + DataColumn( + label: Text('Stok Terkini'), + ), + ], + rows: _arrayPenjualan + .map((Map laporan) => DataRow( + cells: [ + DataCell(Text(laporan['kode_barang']!)), + DataCell(Text(laporan['jumlah']!.toString())), + DataCell(Text("Rp. ${laporan['harga_jual']!}")), + DataCell(Text("Rp. ${formatter.format(laporan['total'])}")), + DataCell( + Text(laporan['jumlah_stok_sebelumnya']!.toString())), + DataCell(Text(laporan['jumlah_stok_sekarang']!.toString())), + ], + )) + .toList(), + ); + + _detail = Column( + children: [ + Text("Total Belanja : Rp. ${_ket['total_belanja']}"), + const Divider( + color: Colors.black, + ), + Text("Pembayaran : Rp. ${_ket['pembayaran']}"), + const Divider( + color: Colors.black, + ), + Text("Kembalian : Rp. ${_ket['baki']}"), + const Divider( + color: Colors.black, + ), + const SizedBox( + height: 10, + ), + SingleChildScrollView( + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, child: _widgetTabel), + ), + ], + ); + } else if (_result['status'] == 'Edit Detail Produk') { + // ignore: prefer_typing_uninitialized_variables + var _namanya, _harganya, _fotonya; + if (_ket['nama_lama'] != _ket['nama_baru']) { + _namanya = Column( + children: [ + Text('Nama : ${_ket['nama_lama']} => ${_ket['nama_baru']}'), + const Divider( + color: Colors.black, + ), + ], + ); + } else { + _namanya = const SizedBox(); + } + + if (_ket['harga_lama'] != _ket['harga_baru']) { + _harganya = Column( + children: [ + Text( + 'Harga : Rp. ${_ket['harga_lama']} => Rp. ${_ket['harga_baru']}'), + const Divider( + color: Colors.black, + ), + ], + ); + } else { + _harganya = const SizedBox(); + } + + if (_ket['foto_lama'] != _ket['foto_baru']) { + _fotonya = Text('Foto : ${_ket['foto_lama']} => ${_ket['foto_baru']}'); + } else { + _fotonya = const SizedBox(); + } + + _detail = Column( + children: [ + _namanya, + _harganya, + _fotonya, + ], + ); + } else if (_result['status'] == 'Penambahan Stok') { + _detail = Column( + children: [ + Text("Penambahan Stok : ${_ket['penambahan_stok']}"), + const Divider( + color: Colors.black, + ), + Text("Harga Pembelian : Rp. ${_ket['harga_pembelian_stok']}"), + const Divider( + color: Colors.black, + ), + Text("Stok Sebelumnya : ${_ket['jumlah_stok_sebelumnya']}"), + const Divider( + color: Colors.black, + ), + Text("Stok Baru : ${_ket['total_stok']}"), + const Divider( + color: Colors.black, + ), + ], + ); + } else if (_result['status'] == 'Penambahan Produk Baru') { + _detail = Column( + children: [ + Text("Kode Barang : ${_ket['kode_barang']}"), + const Divider( + color: Colors.black, + ), + Text("Nama Barang : ${_ket['nama']}"), + const Divider( + color: Colors.black, + ), + Text("Harga Jual : Rp. ${_ket['harga_jual']}"), + const Divider( + color: Colors.black, + ), + Text("Harga Pembelian Stok : Rp. ${_ket['pembelian_stok']}"), + const Divider( + color: Colors.black, + ), + Text("Jumlah : ${_ket['jumlah']}"), + const Divider( + color: Colors.black, + ), + ], + ); + } else { + _detail = Container(); + } + + return Container( + width: MediaQuery.of(context).size.width * 0.85, + padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20, top: 10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(20), + boxShadow: const [ + BoxShadow( + color: Colors.grey, + blurRadius: 10, + spreadRadius: 1, + offset: Offset( + 4, + 4, + ), + ), + ]), + child: Column( + children: [ + Text("Waktu : ${_result['waktu']}"), + const Divider( + color: Colors.black, + ), + Text("Status : ${_result['status']}"), + const Divider( + color: Colors.black, + ), + _detail, + ], + ), + ); + } + + @override + void initState() { + super.initState(); + FocusManager.instance.primaryFocus?.unfocus(); + _ambilLaporan(_tanggal, '', '', '', context); + } + + // final DataTableSource _data = MyData(); + // ignore: prefer_final_fields + int _currentSortColumn = 0; + bool _isAscending = true; + + // bool _buttonFilter = false; + + final _formKey = GlobalKey(); + final TextEditingController _filterLaporan = TextEditingController(); + + @override + Widget build(BuildContext context) { + // return Scaffold + return Scaffold( + body: SingleChildScrollView( + child: Column( + children: [ + const SizedBox( + height: 10, + ), + OurContainer( + child: Column( + children: [ + const Align( + alignment: Alignment.topLeft, + child: Text( + "Form Pilih Bulan / Tahun Laporan", + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + const SizedBox( + height: 10, + ), + TextField( + enabled: false, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + ), + isDense: true, + hintText: _hintTextBulanTahun, + filled: true, + fillColor: const Color.fromARGB(255, 247, 247, 247), + ), + ), + + const SizedBox( + height: 10, + ), + const SizedBox( + height: 10, + ), + + //create elevated button + ElevatedButton( + child: const Text('Klik Untuk Pilih Bulan / Tanggal'), + onPressed: () { + showMonthPicker( + context: context, + firstDate: DateTime(DateTime.now().year - 1), + lastDate: DateTime.now(), + initialDate: DateTime.now(), + locale: const Locale("id"), + ).then((date) { + // get only month and year on date + + setState(() { + _tanggal = ''; + _bulan = date!.month; + _year = date.year; + _hintTextBulanTahun = + 'Bulan ${_bulan.toString()} / Tahun ${_year.toString()}'; + _headerLaporan = + "Laporan Bulan ${_bulan.toString()} / Tahun ${_year.toString()}"; + }); + _ambilLaporan('', _bulan.toString(), _year.toString(), + '', context); + // _tanggal = date.day.toString(); + }); + }, + ), + ], + ), + ), + const SizedBox( + height: 30, + ), + OurContainer( + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text( + _headerLaporan, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + ), + //create data table with column "Waktu", "Status", "Aksi" and 10 rows + const SizedBox( + height: 10, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Flexible( + child: Form( + key: _formKey, + child: TextFormField( + controller: _filterLaporan, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + ), + isDense: true, + hintText: 'Berdasarkan Waktu / Status', + filled: true, + fillColor: + const Color.fromARGB(255, 247, 247, 247), + ), + ), + ), + ), + const SizedBox(width: 20), + ElevatedButton( + style: ElevatedButton.styleFrom( + primary: Colors.blue, + ), + onPressed: () { + if (_tanggal == '') { + _ambilLaporan('', _bulan.toString(), + _year.toString(), _filterLaporan.text, context); + } else { + _ambilLaporan( + _tanggal, '', '', _filterLaporan.text, context); + } + FocusManager.instance.primaryFocus?.unfocus(); + }, + child: const Text('Filter'), + ), + ], + ), + + _tampilkanLaporan() + ], + ), + ), + const SizedBox( + height: 30, + ), + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: () { + showDialog( + context: context, + builder: (context) => AlertDialog( + // title: const Text('Yakin?'), + content: const Text( + 'Ubah Seluruh Laporan Menjadi Sudah Dibaca?', + textAlign: TextAlign.center, + ), + actions: [ + Center( + child: ElevatedButton( + onPressed: () async { + final BossController _provider = + Provider.of(context, listen: false); + + try { + await _provider.laporanReadAll(); + ScaffoldMessenger.of(context) + .showSnackBar(const SnackBar( + content: Text("Semua Laporan Diubah Menjadi Terbaca"), + )); + } catch (e) { + ScaffoldMessenger.of(context) + .showSnackBar(const SnackBar( + content: Text( + "Koneksi Ke Server Bermasalah, Sila Periksa Jaringan Anda"), + )); + } + Navigator.of(context).pop(true); + }, + style: ElevatedButton.styleFrom( + primary: Colors.blue, + ), + child: const Text( + 'Ya', + textAlign: TextAlign.center, + ), + ), + ), + ], + ), + ); + }, + child: const Icon(Icons.sticky_note_2_outlined), + ), + floatingActionButtonLocation: FloatingActionButtonLocation.miniStartFloat, + ); + } + + Widget _tampilkanLaporan() { + //create switch case + switch (_loadingLaporan) { + case 0: + return Column( + children: const [ + SizedBox( + height: 30, + ), + Center( + child: CircularProgressIndicator(), + ), + ], + ); + case 1: + // ignore: sized_box_for_whitespace + return Container( + height: 400, + child: SingleChildScrollView( + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: DataTable( + columns: [ + DataColumn( + label: const Text('Waktu'), + onSort: (columnIndex, _) { + setState(() { + if (_isAscending == false) { + _laporan.sort((a, b) { + return b['waktu']!.compareTo(a['waktu']!); + }); + _isAscending = true; + } else { + _isAscending = false; + _laporan.sort((a, b) { + return a['waktu']!.compareTo(b['waktu']!); + }); + } + }); + }, + ), + DataColumn( + label: const Text('Status'), + onSort: (columnIndex, _) { + setState(() { + if (_isAscending == false) { + _laporan.sort((a, b) { + return b['status']!.compareTo(a['status']!); + }); + _isAscending = true; + } else { + _isAscending = false; + _laporan.sort((a, b) { + return a['status']!.compareTo(b['status']!); + }); + } + }); + }, + ), + const DataColumn(label: Text('Aksi')), + ], + //rows = _laporan + rows: _laporan + .map((Map laporan) => DataRow( + cells: [ + DataCell(Text(laporan['waktu']!)), + DataCell(Text(laporan['status']!)), + DataCell( + Row( + children: [ + IconButton( + icon: const Icon(Icons.article), + color: Colors.blue, + onPressed: () { + _ambilLaporanDetail( + laporan['no_log']!.toString(), + context); + }, + ) + ], + ), + ), + ], + )) + .toList(), + sortColumnIndex: _currentSortColumn, + sortAscending: _isAscending, + ), + ), + ), + ); + + case 2: + return Column( + children: const [ + SizedBox( + height: 20, + ), + Align( + child: Text('Tidak ada laporan untuk filter ini'), + ), + ], + ); + + case 3: + return Column( + children: const [ + SizedBox( + height: 20, + ), + Align( + child: Text( + 'Koneksi ke server gagal, Sila Cek Koneksi Internet Anda'), + ), + ], + ); + + default: + return Container(); + } + } +} diff --git a/boss_app2/lib/page/boss/index.dart b/boss_app2/lib/page/boss/index.dart new file mode 100644 index 0000000..1bdb6dd --- /dev/null +++ b/boss_app2/lib/page/boss/index.dart @@ -0,0 +1,77 @@ +import 'package:boss_app2/page/boss/homeAdmin.dart'; +import 'package:boss_app2/page/boss/laporanPenuh.dart'; +import 'package:boss_app2/page/boss/produk.dart'; +import 'package:flutter/material.dart'; + +class BossIndex extends StatefulWidget { + @override + _BossIndexState createState() => _BossIndexState(); +} + +class _BossIndexState extends State { + Future _onWillPop() async { + return (await showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text('Yakin?'), + content: const Text('Anda Akan Keluar Dari Aplikasi'), + actions: [ + ElevatedButton( + onPressed: () => Navigator.of(context).pop(false), + child: const Text('Tidak'), + ), + ElevatedButton( + onPressed: () => Navigator.of(context).pop(true), + style: ElevatedButton.styleFrom( + primary: Colors.red, + ), + child: const Text('Ya'), + ), + ], + ), + )) ?? + false; + } + + @override + Widget build(BuildContext context) { + // return Scaffold + return WillPopScope( + onWillPop: _onWillPop, + child: DefaultTabController( + length: 3, + child: Scaffold( + appBar: AppBar( + toolbarHeight: AppBar().preferredSize.height + 8, + flexibleSpace: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: const [ + TabBar(tabs: [ + Tab( + text: 'Home', + icon: Icon(Icons.home), + ), + Tab( + text: 'Log Produk', + icon: Icon(Icons.filter_vintage_sharp), + ), + Tab( + text: 'Laporan Penuh', + icon: Icon(Icons.checklist_rtl_rounded), + ), + ]) + ], + ), + ), + body: TabBarView( + children: [ + HomeAdmin(), + // ProdukAdmin(), + ProdukAdmin(), + const LaporanPenuh(), + ], + )), + ), + ); + } +} diff --git a/boss_app2/lib/page/boss/laporanPenuh.dart b/boss_app2/lib/page/boss/laporanPenuh.dart new file mode 100644 index 0000000..5465114 --- /dev/null +++ b/boss_app2/lib/page/boss/laporanPenuh.dart @@ -0,0 +1,667 @@ +import 'dart:convert'; + +import 'package:boss_app2/widgets/ourContainer.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; + +import '../../controller/boss_controller.dart'; + +class LaporanPenuh extends StatefulWidget { + const LaporanPenuh({Key? key}) : super(key: key); + + @override + _LaporanPenuhState createState() => _LaporanPenuhState(); +} + +class _LaporanPenuhState extends State { + late List> _laporanAll; + int _loadingLaporanAll = 0; + late int _pageNumber; + int _pageNumberIndex = 1; + String _cekFilter = 'tiada'; + String _filterLaporan = ''; + final _inputFilterLaporan = TextEditingController(); + + // ignore: avoid_void_async + void _ambilLaporanAll(BuildContext context, int pageNumber, String filter, + String cekFilter) async { + setState(() { + _loadingLaporanAll = 0; + _pageNumberIndex = pageNumber; + _cekFilter = cekFilter; + _filterLaporan = filter; + }); + _laporanAll = []; + final BossController _toController = + Provider.of(context, listen: false); + + try { + final Map _data = + await _toController.ambilLaporanAll(pageNumber, filter, cekFilter); + + if (_data['status'] == 'success') { + //loop the _data['data'] and push to _laporan by field waktu, status, dan ket + if (_data['data'].length > 0) { + _laporanAll = (_data['data'] as List) + .map((dynamic item) => item as Map) + .toList(); + setState(() { + _loadingLaporanAll = 1; + _pageNumber = (_data['ceil'] / 10).ceil(); + }); + } else { + setState(() { + _loadingLaporanAll = 2; + }); + } + } else if (_data['status'] == 'error') { + setState(() { + _loadingLaporanAll = 3; + }); + } + } catch (e) { + setState(() { + _loadingLaporanAll = 3; + }); + } + } + + @override + void initState() { + super.initState(); + _ambilLaporanAll(context, _pageNumberIndex, _filterLaporan, _cekFilter); + FocusManager.instance.primaryFocus?.unfocus(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: SingleChildScrollView( + child: Column( + children: [ + const SizedBox( + height: 20, + ), + OurContainer( + child: Column( + children: [ + const Align( + alignment: Alignment.topLeft, + child: Text( + "Filter Laporan", + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + const SizedBox( + height: 10, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Flexible( + child: TextFormField( + controller: _inputFilterLaporan, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + ), + isDense: true, + hintText: 'Kode / Nama Produk', + filled: true, + fillColor: const Color.fromARGB(255, 247, 247, 247), + ), + ), + ), + const SizedBox(width: 20), + ElevatedButton( + onPressed: () { + if (_inputFilterLaporan.text == '') { + _ambilLaporanAll( + context, 1, _filterLaporan, 'tiada'); + } else { + _ambilLaporanAll( + context, 1, _inputFilterLaporan.text, 'ada'); + } + FocusManager.instance.primaryFocus?.unfocus(); + }, + child: const Text('Filter'), + ), + ], + ), + ], + ), + ), + const SizedBox( + height: 20, + ), + OurContainer( + child: (_loadingLaporanAll == 0) + ? Column( + children: const [ + SizedBox(height: 25), + Center(child: CircularProgressIndicator()) + ], + ) + : (_loadingLaporanAll == 2) + ? Column( + children: const [ + SizedBox(height: 25), + Center( + child: Text( + 'Koneksi Ke Server Bermasalah, Sila Periksa Jaringan Anda'), + ) + ], + ) + : (_loadingLaporanAll == 1) + ? Column( + children: [ + Container( + constraints: const BoxConstraints( + maxHeight: 450, + ), + child: SingleChildScrollView( + child: Column( + children: [ + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: DataTable( + columns: const [ + DataColumn(label: Text('No')), + DataColumn( + label: Text('Waktu')), + DataColumn( + label: Text('Status')), + DataColumn( + label: Text('Keterangan')), + ], + rows: _laporanAll.map( + (Map item) { + return DataRow( + cells: [ + // DataCell(Text('${_laporanAll.indexOf(item) + 1}')), + DataCell(Text( + '${item['no_log']}')), + DataCell(Text( + '${item['waktu']}')), + DataCell(Text( + '${item['status']}')), + DataCell(IconButton( + icon: const Icon( + Icons.article), + color: Colors.blue, + onPressed: () { + _bottomSheetModal( + context, item); + }, + )), + ], + ); + }).toList(), + ), + ), + ], + ), + ), + ), + _pageButton(context), + ], + ) + : const SizedBox()), + const SizedBox( + height: 30, + ), + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: () { + showDialog( + context: context, + builder: (context) => AlertDialog( + // title: const Text('Yakin?'), + content: const Text( + 'Ubah Seluruh Laporan Menjadi Sudah Dibaca?', + textAlign: TextAlign.center, + ), + actions: [ + Center( + child: ElevatedButton( + onPressed: () async { + final BossController _provider = + Provider.of(context, listen: false); + + try { + await _provider.laporanReadAll(); + ScaffoldMessenger.of(context) + .showSnackBar(const SnackBar( + content: Text("Semua Laporan Diubah Menjadi Terbaca"), + )); + } catch (e) { + ScaffoldMessenger.of(context) + .showSnackBar(const SnackBar( + content: Text( + "Koneksi Ke Server Bermasalah, Sila Periksa Jaringan Anda"), + )); + } + Navigator.of(context).pop(true); + }, + style: ElevatedButton.styleFrom( + primary: Colors.blue, + ), + child: const Text( + 'Ya', + textAlign: TextAlign.center, + ), + ), + ), + ], + ), + ); + }, + child: const Icon(Icons.sticky_note_2_outlined), + ), + floatingActionButtonLocation: FloatingActionButtonLocation.miniStartFloat, + ); + } + + SingleChildScrollView _pageButton(BuildContext context) { + final List _pageButton = []; + + if (_loadingLaporanAll == 1) { + if (_pageNumber >= 1 && _pageNumber <= 3) { + for (int i = 1; i <= _pageNumber; i++) { + _pageButton.add( + ElevatedButton( + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + primary: (_pageNumberIndex == 1 && i == 1) + ? Colors.grey + : (_pageNumberIndex == 2 && i == 2) + ? Colors.grey + : (_pageNumberIndex == 3 && i == 3) + ? Colors.grey + : Colors.blue, + ), + onPressed: () { + if (_pageNumberIndex == 1 && i == 1) { + } else if (_pageNumberIndex == 2 && i == 2) { + } else if (_pageNumberIndex == 3 && i == 3) { + } else { + setState(() { + _pageNumberIndex = i; + // _pageNumber = i; + }); + _ambilLaporanAll(context, i, _filterLaporan, _cekFilter); + } + }, + child: Text(i.toString()), + ), + ); + } + } else if (_pageNumber > 3) { + _pageButton.add( + ElevatedButton( + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + primary: (_pageNumberIndex != 1) ? Colors.blue : Colors.grey, + ), + onPressed: () { + _ambilLaporanAll( + context, _pageNumberIndex - 1, _filterLaporan, _cekFilter); + }, + child: const Text('<'), + ), + ); + _pageButton.add( + ElevatedButton( + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + primary: (_pageNumberIndex != 1) ? Colors.blue : Colors.grey, + ), + onPressed: () { + _ambilLaporanAll(context, 1, _filterLaporan, _cekFilter); + }, + child: const Text('1'), + ), + ); + _pageButton.add( + const Text('...'), + ); + + if (_pageNumberIndex != 1 && _pageNumberIndex != _pageNumber) { + _pageButton.add( + ElevatedButton( + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + primary: Colors.grey, + ), + onPressed: () {}, + child: Text(_pageNumberIndex.toString()), + ), + ); + _pageButton.add( + const Text('...'), + ); + } + + _pageButton.add( + ElevatedButton( + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + primary: + (_pageNumberIndex != _pageNumber) ? Colors.blue : Colors.grey, + ), + onPressed: () { + _ambilLaporanAll( + context, _pageNumber, _filterLaporan, _cekFilter); + }, + child: Text(_pageNumber.toString()), + ), + ); + _pageButton.add( + ElevatedButton( + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + primary: + (_pageNumberIndex != _pageNumber) ? Colors.blue : Colors.grey, + ), + onPressed: () { + _ambilLaporanAll( + context, _pageNumberIndex + 1, _filterLaporan, _cekFilter); + }, + child: const Text('>'), + ), + ); + } + } else { + _pageButton.add(const SizedBox()); + } + + return SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: _pageButton, + ), + ); + } + + // ignore: avoid_void_async + void _bottomSheetModal( + BuildContext context, Map _result) async { + final BossController _provider = + Provider.of(context, listen: false); + + try { + await _provider.laporanRead(_result['no_log'].toString()); + } catch (e) { + // print(e); + } + + return showModalBottomSheet( + isScrollControlled: true, + context: context, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + builder: (context) => SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox( + height: 20, + ), + Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Row( + children: [ + SizedBox( + width: (MediaQuery.of(context).size.width - + (MediaQuery.of(context).size.width * 0.8)) / + 2, + ), + const Text( + 'Detail Laporan', + style: TextStyle(fontWeight: FontWeight.bold), + ), + ], + ), + ), + const SizedBox( + height: 10, + ), + _detailLaporan(_result), + ], + ), + const SizedBox( + height: 30, + ), + ], + ), + ), + ); + } + + Widget _detailLaporan(Map _result) { + FocusManager.instance.primaryFocus?.unfocus(); + final Map _ket = jsonDecode(_result['ket']); + // ignore: prefer_typing_uninitialized_variables + var _detail; + final formatter = NumberFormat('#,000'); + + if (_result['status'] == 'Penjualan Produk') { + //create var list map + final List> _arrayPenjualan = (_ket['ket'] as List) + .map((dynamic item) => item as Map) + .toList(); + + final _widgetTabel = DataTable( + columns: const [ + DataColumn( + label: Text('Kode Barang'), + ), + DataColumn( + label: Text('Jumlah'), + ), + DataColumn( + label: Text('Harga Jual'), + ), + DataColumn( + label: Text('Total'), + ), + DataColumn( + label: Text('Stok Sebelumnya'), + ), + DataColumn( + label: Text('Stok Terkini'), + ), + ], + rows: _arrayPenjualan + .map((Map laporan) => DataRow( + cells: [ + DataCell(Text(laporan['kode_barang']!)), + DataCell(Text(laporan['jumlah']!.toString())), + DataCell(Text("Rp. ${laporan['harga_jual']!}")), + DataCell(Text("Rp. ${formatter.format(laporan['total'])}")), + DataCell( + Text(laporan['jumlah_stok_sebelumnya']!.toString())), + DataCell(Text(laporan['jumlah_stok_sekarang']!.toString())), + ], + )) + .toList(), + ); + + _detail = Column( + children: [ + Text("Total Belanja : Rp. ${_ket['total_belanja']}"), + const Divider( + color: Colors.black, + ), + Text("Pembayaran : Rp. ${_ket['pembayaran']}"), + const Divider( + color: Colors.black, + ), + Text("Kembalian : Rp. ${_ket['baki']}"), + const Divider( + color: Colors.black, + ), + const SizedBox( + height: 10, + ), + SingleChildScrollView( + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, child: _widgetTabel), + ), + ], + ); + } else if (_result['status'] == 'Edit Detail Produk') { + // ignore: prefer_typing_uninitialized_variables + var _namanya, _harganya, _fotonya; + if (_ket['nama_lama'] != _ket['nama_baru']) { + _namanya = Column( + children: [ + Text('Nama : ${_ket['nama_lama']} => ${_ket['nama_baru']}'), + const Divider( + color: Colors.black, + ), + ], + ); + } else { + _namanya = const SizedBox(); + } + + if (_ket['harga_lama'] != _ket['harga_baru']) { + _harganya = Column( + children: [ + Text( + 'Harga : Rp. ${_ket['harga_lama']} => Rp. ${_ket['harga_baru']}'), + const Divider( + color: Colors.black, + ), + ], + ); + } else { + _harganya = const SizedBox(); + } + + if (_ket['foto_lama'] != _ket['foto_baru']) { + _fotonya = Text('Foto : ${_ket['foto_lama']} => ${_ket['foto_baru']}'); + } else { + _fotonya = const SizedBox(); + } + + _detail = Column( + children: [ + _namanya, + _harganya, + _fotonya, + ], + ); + } else if (_result['status'] == 'Penambahan Stok') { + _detail = Column( + children: [ + Text("Penambahan Stok : ${_ket['penambahan_stok']}"), + const Divider( + color: Colors.black, + ), + Text("Harga Pembelian : Rp. ${_ket['harga_pembelian_stok']}"), + const Divider( + color: Colors.black, + ), + Text("Stok Sebelumnya : ${_ket['jumlah_stok_sebelumnya']}"), + const Divider( + color: Colors.black, + ), + Text("Stok Baru : ${_ket['total_stok']}"), + const Divider( + color: Colors.black, + ), + ], + ); + } else if (_result['status'] == 'Penambahan Produk Baru') { + _detail = Column( + children: [ + Text("Kode Barang : ${_ket['kode_barang']}"), + const Divider( + color: Colors.black, + ), + Text("Nama Barang : ${_ket['nama']}"), + const Divider( + color: Colors.black, + ), + Text("Harga Jual : Rp. ${_ket['harga_jual']}"), + const Divider( + color: Colors.black, + ), + Text("Harga Pembelian Stok : Rp. ${_ket['pembelian_stok']}"), + const Divider( + color: Colors.black, + ), + Text("Jumlah : ${_ket['jumlah']}"), + const Divider( + color: Colors.black, + ), + ], + ); + } else if (_result['status'] == 'Penjualan Barang Spesifik') { + _detail = Column( + children: [ + Text("Jumlah Pembelian : ${_ket['jumlah_pembelian']}"), + const Divider( + color: Colors.black, + ), + Text("Harga Jual : Rp. ${_ket['harga_jual']}"), + const Divider( + color: Colors.black, + ), + Text("Stok Sebelumnya : ${_ket['stok_sebelumnya']}"), + const Divider( + color: Colors.black, + ), + Text("Stok Terbaru : ${_ket['stok_sekarang']}"), + const Divider( + color: Colors.black, + ), + ], + ); + } else { + _detail = Container(); + } + + return Container( + width: MediaQuery.of(context).size.width * 0.85, + padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20, top: 10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(20), + boxShadow: const [ + BoxShadow( + color: Colors.grey, + blurRadius: 10, + spreadRadius: 1, + offset: Offset( + 4, + 4, + ), + ), + ]), + child: Column( + children: [ + Text("Waktu : ${_result['waktu']}"), + const Divider( + color: Colors.black, + ), + Text( + "Status : ${(_result['status'] == 'Penjualan Barang Spesifik') ? 'Penjualan' : _result['status'].toString()}"), + const Divider( + color: Colors.black, + ), + _detail, + ], + ), + ); + } +} diff --git a/boss_app2/lib/page/boss/produk.dart b/boss_app2/lib/page/boss/produk.dart new file mode 100644 index 0000000..03ff225 --- /dev/null +++ b/boss_app2/lib/page/boss/produk.dart @@ -0,0 +1,440 @@ +import 'package:boss_app2/controller/boss_controller.dart'; +import 'package:boss_app2/global.dart' as globals; +import 'package:boss_app2/page/boss/produkDetail.dart'; +import 'package:boss_app2/widgets/ourContainer.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class ProdukAdmin extends StatefulWidget { + // const ProdukAdmin({Key? key}) : super(key: key); + @override + _ProdukAdminState createState() => _ProdukAdminState(); +} + +class _ProdukAdminState extends State { + late List> _produkAll; + int _loadingProdukAll = 0; + late int _pageNumber; + int _pageNumberIndex = 1; + String _cekFilter = 'tiada'; + + // ignore: avoid_void_async + void _ambilProdukAll(BuildContext context, int pageNumber, String filter, + String cekFilter) async { + setState(() { + _loadingProdukAll = 0; + _pageNumberIndex = pageNumber; + _cekFilter = cekFilter; + }); + _produkAll = []; + final BossController _toController = + Provider.of(context, listen: false); + + try { + final Map _data = + await _toController.ambilProdukAll(pageNumber, filter, cekFilter); + + if (_data['status'] == 'success') { + //loop the _data['data'] and push to _laporan by field waktu, status, dan ket + if (_data['data'].length > 0) { + _produkAll = (_data['data'] as List) + .map((dynamic item) => item as Map) + .toList(); + setState(() { + _loadingProdukAll = 1; + _pageNumber = (_data['ceil'] / 10).ceil(); + }); + } else { + setState(() { + _loadingProdukAll = 2; + }); + } + } else if (_data['status'] == 'error') { + setState(() { + _loadingProdukAll = 3; + }); + } + } catch (e) { + setState(() { + _loadingProdukAll = 3; + }); + } + } + + @override + void initState() { + FocusManager.instance.primaryFocus?.unfocus(); + _ambilProdukAll(context, 1, '', _cekFilter); + + super.initState(); + } + + final TextEditingController _filterProduk = TextEditingController(); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: SingleChildScrollView( + child: Column( + children: [ + const SizedBox(height: 20), + OurContainer( + child: Column( + children: [ + const Align( + alignment: Alignment.topLeft, + child: Text( + "Filter Produk", + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + const SizedBox( + height: 10, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Flexible( + child: TextFormField( + controller: _filterProduk, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + ), + isDense: true, + hintText: 'Kode / Nama Produk', + filled: true, + fillColor: const Color.fromARGB(255, 247, 247, 247), + ), + ), + ), + const SizedBox(width: 20), + ElevatedButton( + onPressed: () { + FocusManager.instance.primaryFocus?.unfocus(); + if (_filterProduk.text == '') { + _ambilProdukAll(context, 1, '', 'tiada'); + } else { + _ambilProdukAll( + context, 1, _filterProduk.text, 'ada'); + } + }, + child: const Text('Cari'), + ), + ], + ), + const SizedBox(height: 20), + if (_loadingProdukAll == 0) + const Center(child: CircularProgressIndicator()) + else if (_loadingProdukAll == 1) + SizedBox( + height: 400, + child: SingleChildScrollView( + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Column( + children: [ + DataTable( + columns: const [ + DataColumn( + label: Text('Kode'), + ), + DataColumn( + label: Text('Nama'), + ), + DataColumn( + label: Text('Harga'), + ), + DataColumn( + label: Text('Stok'), + ), + DataColumn( + label: Text('Laporan'), + ), + ], + rows: _produkAll + .map((Map item) => DataRow( + cells: [ + DataCell( + Row( + children: [ + Text(item['kode_barang'] + .toString()), + const SizedBox(width: 10), + GestureDetector( + onTap: () => _tampilkanFoto( + context, + item['no_barang'], + item['foto']), + child: Hero( + tag: + "image${item['no_barang']}", + child: CircleAvatar( + radius: 15, + backgroundImage: + NetworkImage( + "${globals.http_to_server}img/${item['no_barang']}/${item['foto']}", + ), + ), + ), + ), + ], + ), + ), + DataCell( + Text(item['nama'].toString()), + ), + DataCell( + Text("Rp. ${item['harga_jual']}"), + ), + DataCell( + Text(item['jumlah'].toString()), + ), + DataCell(IconButton( + icon: const Icon(Icons.article), + color: Colors.blue, + onPressed: () { + // _ambilLaporanProduk( + // context, + // int.parse( + // item['no_barang']), + // 1, + // item); + + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + ProdukDetail( + no_log: int.parse( + item['no_barang']), + ), + )); + }, + )), + ], + )) + .toList(), + ), + _pageButton(), + ], + ), + ), + ), + ) + else if (_loadingProdukAll == 2) + const Text( + 'Tidak ada data', + textAlign: TextAlign.center, + ) + else if (_loadingProdukAll == 3) + const Text( + 'Koneksi Ke Server Bermasalah, Sila Periksa Jaringan Anda', + textAlign: TextAlign.center, + ) + ], + ), + ), + const SizedBox(height: 20), + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: () { + showDialog( + context: context, + builder: (context) => AlertDialog( + // title: const Text('Yakin?'), + content: const Text( + 'Ubah Seluruh Laporan Menjadi Sudah Dibaca?', + textAlign: TextAlign.center, + ), + actions: [ + Center( + child: ElevatedButton( + onPressed: () async { + final BossController _provider = + Provider.of(context, listen: false); + + try { + await _provider.laporanReadAll(); + ScaffoldMessenger.of(context) + .showSnackBar(const SnackBar( + content: Text("Semua Laporan Diubah Menjadi Terbaca"), + )); + } catch (e) { + ScaffoldMessenger.of(context) + .showSnackBar(const SnackBar( + content: Text( + "Koneksi Ke Server Bermasalah, Sila Periksa Jaringan Anda"), + )); + } + Navigator.of(context).pop(true); + }, + style: ElevatedButton.styleFrom( + primary: Colors.blue, + ), + child: const Text( + 'Ya', + textAlign: TextAlign.center, + ), + ), + ), + ], + ), + ); + }, + child: const Icon(Icons.sticky_note_2_outlined), + ), + floatingActionButtonLocation: FloatingActionButtonLocation.miniStartFloat, + ); + } + + Future _tampilkanFoto( + BuildContext context, String item, String foto) { + return showModalBottomSheet( + isScrollControlled: true, + context: context, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + builder: (context) => SingleChildScrollView( + child: Column( + children: [ + Hero( + tag: 'image$item', + child: ClipRRect( + borderRadius: BorderRadius.circular(20), + child: Image.network( + "${globals.http_to_server}img/$item/$foto", + ), + ), + ), + ], + ), + ), + ); + } + + Row _pageButton() { + final List _pageButton = []; + + if (_loadingProdukAll == 1) { + if (_pageNumber >= 1 && _pageNumber <= 3) { + for (int i = 1; i <= _pageNumber; i++) { + _pageButton.add( + ElevatedButton( + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + primary: (_pageNumberIndex == 1 && i == 1) + ? Colors.grey + : (_pageNumberIndex == 2 && i == 2) + ? Colors.grey + : (_pageNumberIndex == 3 && i == 3) + ? Colors.grey + : Colors.blue, + ), + onPressed: () { + if (_pageNumberIndex == 1 && i == 1) { + // ignore: unnecessary_statements + null; + } else if (_pageNumberIndex == 2 && i == 2) { + // ignore: unnecessary_statements + null; + } else if (_pageNumberIndex == 3 && i == 3) { + // ignore: unnecessary_statements + null; + } else { + setState(() { + _pageNumberIndex = i; + // _pageNumber = i; + }); + _ambilProdukAll(context, i, '', _cekFilter); + } + }, + child: Text(i.toString()), + ), + ); + } + } else if (_pageNumber > 3) { + _pageButton.add( + ElevatedButton( + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + primary: (_pageNumberIndex != 1) ? Colors.blue : Colors.grey, + ), + onPressed: () { + _ambilProdukAll(context, _pageNumberIndex - 1, '', _cekFilter); + }, + child: const Text('<'), + ), + ); + _pageButton.add( + ElevatedButton( + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + primary: (_pageNumberIndex != 1) ? Colors.blue : Colors.grey, + ), + onPressed: () { + _ambilProdukAll(context, 1, '', _cekFilter); + }, + child: const Text('1'), + ), + ); + _pageButton.add( + const Text('...'), + ); + + if (_pageNumberIndex != 1 && _pageNumberIndex != _pageNumber) { + _pageButton.add( + ElevatedButton( + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + primary: Colors.grey, + ), + onPressed: () {}, + child: Text(_pageNumberIndex.toString()), + ), + ); + _pageButton.add( + const Text('...'), + ); + } + + _pageButton.add( + ElevatedButton( + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + primary: + (_pageNumberIndex != _pageNumber) ? Colors.blue : Colors.grey, + ), + onPressed: () { + _ambilProdukAll(context, _pageNumber, '', _cekFilter); + }, + child: Text(_pageNumber.toString()), + ), + ); + _pageButton.add( + ElevatedButton( + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + primary: + (_pageNumberIndex != _pageNumber) ? Colors.blue : Colors.grey, + ), + onPressed: () { + _ambilProdukAll(context, _pageNumberIndex + 1, '', _cekFilter); + }, + child: const Text('>'), + ), + ); + } + } else { + _pageButton.add(const SizedBox()); + } + + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: _pageButton, + ); + } +} diff --git a/boss_app2/lib/page/boss/produkDetail.dart b/boss_app2/lib/page/boss/produkDetail.dart new file mode 100644 index 0000000..957bf22 --- /dev/null +++ b/boss_app2/lib/page/boss/produkDetail.dart @@ -0,0 +1,610 @@ +// ignore_for_file: unnecessary_statements + +import 'dart:convert'; + +import 'package:boss_app2/widgets/ourContainer.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../controller/boss_controller.dart'; + +class ProdukDetail extends StatefulWidget { + // ignore: non_constant_identifier_names + final int no_log; + // ignore: non_constant_identifier_names + const ProdukDetail({Key? key, required this.no_log}) : super(key: key); + + @override + _ProdukDetailState createState() => _ProdukDetailState(); +} + +class _ProdukDetailState extends State { + late Map _dataProduk; + int _loadingProduk = 0; + + // ignore: avoid_void_async + void _ambilProdukDetail(BuildContext context, int noBarang) async { + setState(() { + _loadingProduk = 0; + }); + final BossController _toController = + Provider.of(context, listen: false); + + try { + final Map _data = await _toController.ambilProdukDetail(noBarang); + setState(() { + _dataProduk = _data['data']; + _loadingProduk = 1; + }); + } catch (e) { + setState(() { + _loadingProduk = 2; + }); + } + } + + late List> _laporanProduk; + int _loadingLaporan = 0; + late int _pageNumberLaporan; + int _pageNumberLaporanIndex = 1; + String _filterLaporan = ""; + String _cekFilter = "tiada"; + bool _cekLengthData = false; + + // ignore: avoid_void_async + void _ambilLogLaporan(BuildContext context, int noBarang, int pageNumber, + String filter, String cekFilter) async { + setState(() { + _loadingLaporan = 0; + _pageNumberLaporanIndex = pageNumber; + _cekFilter = cekFilter; + _filterLaporan = filter; + }); + _laporanProduk = []; + final BossController _toController = + Provider.of(context, listen: false); + + try { + final Map _data = await _toController.ambilLaporanProdukDetail( + noBarang, pageNumber, filter, cekFilter); + _laporanProduk = (_data['data'] as List) + .map((dynamic item) => item as Map) + .toList(); + setState(() { + if (_laporanProduk.isEmpty) { + _cekLengthData = false; + } else { + _cekLengthData = true; + } + _laporanProduk = _laporanProduk; + _loadingLaporan = 1; + _pageNumberLaporan = (_data['ceil'] / 10).ceil(); + }); + } catch (e) { + setState(() { + _loadingLaporan = 2; + }); + } + } + + final TextEditingController _inputFilterLaporan = TextEditingController(); + + @override + void initState() { + _ambilLogLaporan(context, widget.no_log, 1, _filterLaporan, _cekFilter); + _ambilProdukDetail(context, widget.no_log); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Detail Produk'), + ), + body: SingleChildScrollView( + child: Column( + children: [ + const SizedBox(height: 10), + OurContainer( + child: (_loadingProduk == 1) + ? Center( + child: Column( + children: [ + Text('Kode : ${_dataProduk['kode_barang']}'), + const Divider( + color: Colors.black, + ), + Text('Nama : ${_dataProduk['nama']}'), + const Divider( + color: Colors.black, + ), + Text('Harga Jual : ${_dataProduk['harga_jual']}'), + const Divider( + color: Colors.black, + ), + Text('Stok : ${_dataProduk['jumlah']}'), + ], + ), + ) + : (_loadingProduk == 0) + ? const Center(child: CircularProgressIndicator()) + : (_loadingProduk == 2) + ? const Center( + child: Text( + 'Koneksi Ke Server Bermasalah, Sila Periksa Jaringan Anda')) + : Container(), + ), + const SizedBox(height: 20), + OurContainer( + child: Center( + child: Column( + children: [ + if (_loadingLaporan == 1) + Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Flexible( + child: TextFormField( + controller: _inputFilterLaporan, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + ), + isDense: true, + hintText: 'Berdasarkan Waktu / Status', + filled: true, + fillColor: const Color.fromARGB( + 255, 247, 247, 247), + ), + ), + ), + const SizedBox(width: 20), + ElevatedButton( + style: ElevatedButton.styleFrom( + primary: Colors.blue, + ), + onPressed: () { + if (_inputFilterLaporan.text == '') { + _ambilLogLaporan(context, widget.no_log, 1, + _inputFilterLaporan.text, 'tiada'); + } else { + _ambilLogLaporan(context, widget.no_log, 1, + _inputFilterLaporan.text, 'ada'); + } + FocusManager.instance.primaryFocus?.unfocus(); + + // } + }, + child: const Text('Filter'), + ), + ], + ), + if (_cekLengthData) + SingleChildScrollView( + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: DataTable( + columns: const [ + DataColumn( + label: Text('No'), + ), + DataColumn( + label: Text('Waktu'), + ), + DataColumn( + label: Text('Status'), + ), + DataColumn( + label: Text('Keterangan'), + ), + ], + rows: _laporanProduk + .map( + (dynamic item) => DataRow( + cells: [ + DataCell( + Text( + item['no_log'].toString(), + ), + ), + DataCell( + Text( + item['waktu'].toString(), + ), + ), + DataCell( + (item['status'] != + "Penjualan Barang Spesifik") + ? Text( + item['status'].toString(), + ) + : const Text("Penjualan"), + ), + DataCell(IconButton( + icon: const Icon(Icons.article), + color: Colors.blue, + onPressed: () { + _bottomSheetModal( + context, item); + }, + )), + ], + ), + ) + .toList(), + ), + ), + ) + else + Column( + children: [ + const SizedBox(height: 20), + Center( + child: Text( + 'Tidak Ada Rekod Laporan Untuk Filter "${_inputFilterLaporan.text}"', + textAlign: TextAlign.center, + )), + ], + ), + ], + ) + else + (_loadingLaporan == 0) + ? const Center( + child: CircularProgressIndicator(), + ) + : (_loadingLaporan == 2) + ? const Center( + child: Text( + 'Koneksi Ke Serverl Bermasalah, Sila Periksa Jaringan Anda', + ), + ) + : Container(), + _pageButton(), + ], + ), + ), + ), + ], + ), + ), + ); + } + + // ignore: avoid_void_async + void _bottomSheetModal( + BuildContext context, Map _result) async { + return showModalBottomSheet( + isScrollControlled: true, + context: context, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + builder: (context) => SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox( + height: 20, + ), + Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Row( + children: [ + SizedBox( + width: (MediaQuery.of(context).size.width - + (MediaQuery.of(context).size.width * 0.8)) / + 2, + ), + const Text( + 'Detail Laporan', + style: TextStyle(fontWeight: FontWeight.bold), + ), + ], + ), + ), + const SizedBox( + height: 10, + ), + _detailLaporan(_result), + ], + ), + const SizedBox( + height: 30, + ), + ], + ), + ), + ); + } + + Widget _detailLaporan(Map _result) { + FocusManager.instance.primaryFocus?.unfocus(); + final Map _ket = jsonDecode(_result['ket']); + // ignore: prefer_typing_uninitialized_variables + var _detail; + + if (_result['status'] == 'Edit Detail Produk') { + // ignore: prefer_typing_uninitialized_variables + var _namanya, _harganya, _fotonya; + if (_ket['nama_lama'] != _ket['nama_baru']) { + _namanya = Column( + children: [ + Text('Nama : ${_ket['nama_lama']} => ${_ket['nama_baru']}'), + const Divider( + color: Colors.black, + ), + ], + ); + } else { + _namanya = const SizedBox(); + } + + if (_ket['harga_lama'] != _ket['harga_baru']) { + _harganya = Column( + children: [ + Text( + 'Harga : Rp. ${_ket['harga_lama']} => Rp. ${_ket['harga_baru']}'), + const Divider( + color: Colors.black, + ), + ], + ); + } else { + _harganya = const SizedBox(); + } + + if (_ket['foto_lama'] != _ket['foto_baru']) { + _fotonya = Text('Foto : ${_ket['foto_lama']} => ${_ket['foto_baru']}'); + } else { + _fotonya = const SizedBox(); + } + + _detail = Column( + children: [ + _namanya, + _harganya, + _fotonya, + ], + ); + } else if (_result['status'] == 'Penambahan Stok') { + _detail = Column( + children: [ + Text("Penambahan Stok : ${_ket['penambahan_stok']}"), + const Divider( + color: Colors.black, + ), + Text("Harga Pembelian : Rp. ${_ket['harga_pembelian_stok']}"), + const Divider( + color: Colors.black, + ), + Text("Stok Sebelumnya : ${_ket['jumlah_stok_sebelumnya']}"), + const Divider( + color: Colors.black, + ), + Text("Stok Baru : ${_ket['total_stok']}"), + const Divider( + color: Colors.black, + ), + ], + ); + } else if (_result['status'] == 'Penambahan Produk Baru') { + _detail = Column( + children: [ + Text("Kode Barang : ${_ket['kode_barang']}"), + const Divider( + color: Colors.black, + ), + Text("Nama Barang : ${_ket['nama']}"), + const Divider( + color: Colors.black, + ), + Text("Harga Jual : Rp. ${_ket['harga_jual']}"), + const Divider( + color: Colors.black, + ), + Text("Harga Pembelian Stok : Rp. ${_ket['pembelian_stok']}"), + const Divider( + color: Colors.black, + ), + Text("Jumlah : ${_ket['jumlah']}"), + const Divider( + color: Colors.black, + ), + ], + ); + } else if (_result['status'] == 'Penjualan Barang Spesifik') { + _detail = Column( + children: [ + Text("Jumlah Pembelian : ${_ket['jumlah_pembelian']}"), + const Divider( + color: Colors.black, + ), + Text("Harga Jual : Rp. ${_ket['harga_jual']}"), + const Divider( + color: Colors.black, + ), + Text("Stok Sebelumnya : ${_ket['stok_sebelumnya']}"), + const Divider( + color: Colors.black, + ), + Text("Stok Terbaru : ${_ket['stok_sekarang']}"), + const Divider( + color: Colors.black, + ), + ], + ); + } else { + _detail = Container(); + } + + return Container( + width: MediaQuery.of(context).size.width * 0.85, + padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20, top: 10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(20), + boxShadow: const [ + BoxShadow( + color: Colors.grey, + blurRadius: 10, + spreadRadius: 1, + offset: Offset( + 4, + 4, + ), + ), + ]), + child: Column( + children: [ + Text("Waktu : ${_result['waktu']}"), + const Divider( + color: Colors.black, + ), + Text( + "Status : ${(_result['status'] == 'Penjualan Barang Spesifik') ? 'Penjualan' : _result['status'].toString()}"), + const Divider( + color: Colors.black, + ), + _detail, + ], + ), + ); + } + + SingleChildScrollView _pageButton() { + final List _pageButton = []; + + if (_loadingLaporan == 1) { + if (_pageNumberLaporan >= 1 && _pageNumberLaporan <= 3) { + for (int i = 1; i <= _pageNumberLaporan; i++) { + _pageButton.add( + ElevatedButton( + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + primary: (_pageNumberLaporanIndex == 1 && i == 1) + ? Colors.grey + : (_pageNumberLaporanIndex == 2 && i == 2) + ? Colors.grey + : (_pageNumberLaporanIndex == 3 && i == 3) + ? Colors.grey + : Colors.blue, + ), + onPressed: () { + if (_pageNumberLaporanIndex == 1 && i == 1) { + } else if (_pageNumberLaporanIndex == 2 && i == 2) { + } else if (_pageNumberLaporanIndex == 3 && i == 3) { + } else { + setState(() { + _pageNumberLaporanIndex = i; + // _pageNumberLaporan = i; + }); + _ambilLogLaporan( + context, widget.no_log, i, _filterLaporan, _cekFilter); + } + }, + child: Text(i.toString()), + ), + ); + } + } else if (_pageNumberLaporan > 3) { + _pageButton.add( + ElevatedButton( + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + primary: + (_pageNumberLaporanIndex != 1) ? Colors.blue : Colors.grey, + ), + onPressed: () { + _ambilLogLaporan(context, widget.no_log, + _pageNumberLaporanIndex - 1, _filterLaporan, _cekFilter); + }, + child: const Text('<'), + ), + ); + _pageButton.add( + ElevatedButton( + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + primary: + (_pageNumberLaporanIndex != 1) ? Colors.blue : Colors.grey, + ), + onPressed: () { + _ambilLogLaporan( + context, widget.no_log, 1, _filterLaporan, _cekFilter); + }, + child: const Text('1'), + ), + ); + _pageButton.add( + const Text('...'), + ); + + if (_pageNumberLaporanIndex != 1 && + _pageNumberLaporanIndex != _pageNumberLaporan) { + _pageButton.add( + ElevatedButton( + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + primary: Colors.grey, + ), + onPressed: () { + null; + }, + child: Text(_pageNumberLaporanIndex.toString()), + ), + ); + _pageButton.add( + const Text('...'), + ); + } + + _pageButton.add( + ElevatedButton( + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + primary: (_pageNumberLaporanIndex != _pageNumberLaporan) + ? Colors.blue + : Colors.grey, + ), + onPressed: () { + _ambilLogLaporan(context, widget.no_log, _pageNumberLaporan, + _filterLaporan, _cekFilter); + }, + child: Text(_pageNumberLaporan.toString()), + ), + ); + _pageButton.add( + ElevatedButton( + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + primary: (_pageNumberLaporanIndex != _pageNumberLaporan) + ? Colors.blue + : Colors.grey, + ), + onPressed: () { + _ambilLogLaporan(context, widget.no_log, + _pageNumberLaporanIndex + 1, _filterLaporan, _cekFilter); + }, + child: const Text('>'), + ), + ); + } + } else { + _pageButton.add(const SizedBox()); + } + + return SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: _pageButton, + ), + ); + } +} diff --git a/boss_app2/lib/page/login.dart b/boss_app2/lib/page/login.dart new file mode 100644 index 0000000..41e6fce --- /dev/null +++ b/boss_app2/lib/page/login.dart @@ -0,0 +1,343 @@ +// ignore_for_file: sized_box_for_whitespace, prefer_const_constructors + +import 'dart:async'; + +import 'package:boss_app2/controller/login_controller.dart'; +import 'package:boss_app2/controller/notification_api.dart'; +import 'package:boss_app2/page/before_login.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class Login extends StatefulWidget { + // ignore: avoid_unused_constructor_parameters, prefer_const_constructors_in_immutables + Login({Key? key, String? payload}) : super(key: key); + + @override + _LoginState createState() => _LoginState(); +} + +class _LoginState extends State { + final _formKey = GlobalKey(); + //create shared prefs + late SharedPreferences sharedPreferences; + //create 2 final variables , one for the username and one for the password = TextEditingController + final TextEditingController _usernameController = TextEditingController(); + final TextEditingController _passwordController = TextEditingController(); + + bool _isLoading = false; + late FocusNode myFocusNode; + + //create void _login with 3 parameters, username, password and context + // ignore: avoid_void_async + void _login(String username, String password, BuildContext context) async { + // create final LoginController loginController = provider.of(context, listen: false); + final LoginController _login = + Provider.of(context, listen: false); + + //create try catch + try { + // final Map _returnString = await _login.login(username, password); + final String _returnString = await _login.login(username, password); + + //create switch case + switch (_returnString) { + case "1": + showDialog( + context: context, + builder: (BuildContext context) { + Future.delayed(const Duration(milliseconds: 2500), () { + // Navigator.of(context).pop(true); + // Navigator.pushAndRemoveUntil( + // context, + // MaterialPageRoute( + // builder: (context) => ScanQRCode(), + // ), + // (route) => false); + }); + return const AlertDialog( + title: Text( + "Sukses", + textAlign: TextAlign.center, + ), + content: Text( + "Selamat Login Kembali", + textAlign: TextAlign.center, + ), + ); + }, + ); + + Future.delayed(const Duration(seconds: 3), () { + // Navigator.of(context).pop(true); + Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute( + builder: (context) => BeforeLogin(), + ), + (route) => false); + }); + + break; + + case "2": + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: const Text("Username Dan Password Salah"), + )); + //focus node + myFocusNode.requestFocus(); + break; + + case "3": + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: const Text( + "Error Koneksi Ke Server, Sila Periksa Jaringan Anda"), + )); + + break; + } + + setState(() { + _isLoading = false; + }); + } catch (e) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: + const Text("Error Koneksi Ke Server, Sila Periksa Jaringan Anda"), + )); + setState(() { + _isLoading = false; + }); + } + } + + // ignore: avoid_void_async, unused_element + // void _notification() async { + // final LoginController _login = + // Provider.of(context, listen: false); + + // //create try catch + // try { + // // final Map _returnString = await _login.login(username, password); + // final List _returnString = await _login.getNotif(); + // List ini = [1, 2, 3, 4, 5]; + // bool cek = false; + // int jumlah = _returnString.length; + // List notif = []; + // for (var i = 0; i < _returnString.length; i++) { + // cek = false; + // for (var j = 0; j < ini.length; j++) { + // if (ini[j].toString() == _returnString[i]['no_log'].toString()) { + // cek = true; + // jumlah = jumlah - 1; + // break; + // } + // } + + // if (cek == false) { + // notif.add(int.parse(_returnString[i]['no_log'])); + // } + // // cek = false; + // } + // } catch (e) { + // } + // // NotificationApi.showNotification( + // // title: 'Notification Title', + // // body: 'Notification Body', + // // payload: 'Notification Payload', + // // ); + // } + + Stream _getnotif(BuildContext context) async* { + // List _list = []; + final LoginController _login = + Provider.of(context, listen: false); + + while (true) { + final int _data = await _login.getNotif(); + await Future.delayed(Duration(seconds: 60)); + yield _data; + } + } + + // late Timer timer; + + FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + + @override + void initState() { + super.initState(); + myFocusNode = FocusNode(); + + // var initializationSettingsAndroid = + // AndroidInitializationSettings('flutter_devs'); + // var initializationSettingsIOs = IOSInitializationSettings(); + // var initSetttings = InitializationSettings( + // android: initializationSettingsAndroid, iOS: initializationSettingsIOs); + // flutterLocalNotificationsPlugin.initialize(initSetttings, + // onSelectNotification: onSelectNotification); + NotificationApi.init(initScheduled: true, context: context); + + // listenNotifications(); + NotificationApi.showScheduleNotification(); + // _notification(); + // timer = Timer.periodic(Duration(seconds: 10), (Timer t) => _notification()); + _getnotif(context).listen((data) async { + if (data > 0) { + NotificationApi.showNotification( + title: 'Laporan Baru', + body: 'Ada $data laporan baru', + payload: 'Laporan Baru', + ); + } + }); + } + + @override + void dispose() { + // timer.cancel(); + super.dispose(); + myFocusNode.dispose(); + } + + // @override + // // ignore: avoid_void_async + // void didChangeDependencies() async { + // super.didChangeDependencies(); + // sharedPreferences = await SharedPreferences.getInstance(); + // sharedPreferences.remove('notif'); + // } + + @override + Widget build(BuildContext context) { + return Scaffold( + //create appbar + appBar: AppBar( + title: const Text('Halaman Login'), + ), + //create body + body: Center( + child: SingleChildScrollView( + reverse: true, + child: _isLoading + ? const Center(child: CircularProgressIndicator()) + : Form( + key: _formKey, + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + // ignore: avoid_redundant_argument_values + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + // StreamBuilder(), + Container( + width: MediaQuery.of(context).size.width * 0.8, + child: TextFormField( + focusNode: myFocusNode, + controller: _usernameController, + keyboardType: TextInputType.text, + decoration: const InputDecoration( + border: OutlineInputBorder(), + hintText: "Masukkan Username", + labelText: 'Username', + ), + validator: (value) { + if (value!.isEmpty) { + return 'Masukkan Username'; + } + return null; + }, + ), + ), + const SizedBox( + height: 20, + ), + Container( + width: MediaQuery.of(context).size.width * 0.8, + child: TextFormField( + controller: _passwordController, + keyboardType: TextInputType.text, + obscureText: true, + decoration: const InputDecoration( + border: OutlineInputBorder(), + hintText: "Masukkan Password", + labelText: 'Password', + ), + validator: (value) { + if (value!.isEmpty) { + return 'Masukkan Pasword'; + } + return null; + }, + ), + ), + const SizedBox( + height: 20, + ), + Container( + width: MediaQuery.of(context).size.width * 0.8, + height: 50, + child: ElevatedButton( + child: const Text('Login'), + onPressed: () { + if (_formKey.currentState!.validate()) { + setState(() { + _isLoading = true; + }); + _login(_usernameController.text, + _passwordController.text, context); + } + }, + ), + ), + const SizedBox( + height: 20, + ), + // ElevatedButton( + // onPressed: () { + // NotificationApi.showNotification( + // title: 'Notification Title', + // body: 'Notification Body', + // payload: 'Notification Payload', + // ); + // // _notification(); + // // sharedPreferences.re + // }, + // child: Text('sini'), + // ), + // ElevatedButton( + // onPressed: () { + // // _notification(); + // NotificationApi.showScheduleNotification(); + // }, + // child: Text('sini 2'), + // ), + ], + ), + ), + ), + ), + ), + ); + } + + // void listenNotifications() => + // NotificationApi.onNotifications.stream.listen(onClickedNotification); + + // void onClickedNotification(String? payload) { + // Navigator.of(context).push( + // MaterialPageRoute( + // builder: (context) => Login(payload: payload), + // ), + // ); + // } + // Future onSelectNotification(String payload) { + // Navigator.of(context).push(MaterialPageRoute(builder: (_) { + // return NewScreen(Login); + // })); + + // throw + // } +} diff --git a/boss_app2/lib/page/superadmin/index.dart b/boss_app2/lib/page/superadmin/index.dart new file mode 100644 index 0000000..aa912e8 --- /dev/null +++ b/boss_app2/lib/page/superadmin/index.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; + +class SuperadminIndex extends StatefulWidget { + const SuperadminIndex({Key? key}) : super(key: key); + + @override + _SuperadminIndexState createState() => _SuperadminIndexState(); +} + +class _SuperadminIndexState extends State { + @override + Widget build(BuildContext context) { + // return Scaffold + return Scaffold( + appBar: AppBar( + title: const Text('Superadmin'), + ), + body: const Center( + child: Text('Superadmin'), + ), + ); + } +} diff --git a/boss_app2/lib/widgets/ourContainer.dart b/boss_app2/lib/widgets/ourContainer.dart new file mode 100644 index 0000000..c65f232 --- /dev/null +++ b/boss_app2/lib/widgets/ourContainer.dart @@ -0,0 +1,33 @@ +import 'package:flutter/material.dart'; + +class OurContainer extends StatelessWidget { + final Widget? child; + + const OurContainer({Key? key, this.child}) : super(key: key); + @override + Widget build(BuildContext context) { + final double left = (MediaQuery.of(context).size.width - + (MediaQuery.of(context).size.width * 0.9)) / + 2; + return Container( + width: MediaQuery.of(context).size.width * 0.9, + margin: EdgeInsets.only(left: left), + padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20, top: 10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(20), + boxShadow: const [ + BoxShadow( + color: Colors.grey, + blurRadius: 10, + spreadRadius: 1, + offset: Offset( + 4, + 4, + ), + ), + ]), + child: child, + ); + } +} diff --git a/boss_app2/linux/.gitignore b/boss_app2/linux/.gitignore new file mode 100644 index 0000000..d3896c9 --- /dev/null +++ b/boss_app2/linux/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/boss_app2/linux/CMakeLists.txt b/boss_app2/linux/CMakeLists.txt new file mode 100644 index 0000000..023da2c --- /dev/null +++ b/boss_app2/linux/CMakeLists.txt @@ -0,0 +1,116 @@ +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +set(BINARY_NAME "boss_app2") +set(APPLICATION_ID "com.example.boss_app2") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Configure build options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Application build +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) +apply_standard_settings(${BINARY_NAME}) +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) +add_dependencies(${BINARY_NAME} flutter_assemble) +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/boss_app2/linux/flutter/CMakeLists.txt b/boss_app2/linux/flutter/CMakeLists.txt new file mode 100644 index 0000000..33fd580 --- /dev/null +++ b/boss_app2/linux/flutter/CMakeLists.txt @@ -0,0 +1,87 @@ +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/boss_app2/linux/flutter/generated_plugin_registrant.cc b/boss_app2/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..e71a16d --- /dev/null +++ b/boss_app2/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void fl_register_plugins(FlPluginRegistry* registry) { +} diff --git a/boss_app2/linux/flutter/generated_plugin_registrant.h b/boss_app2/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..e0f0a47 --- /dev/null +++ b/boss_app2/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/boss_app2/linux/flutter/generated_plugins.cmake b/boss_app2/linux/flutter/generated_plugins.cmake new file mode 100644 index 0000000..51436ae --- /dev/null +++ b/boss_app2/linux/flutter/generated_plugins.cmake @@ -0,0 +1,15 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) diff --git a/boss_app2/linux/main.cc b/boss_app2/linux/main.cc new file mode 100644 index 0000000..e7c5c54 --- /dev/null +++ b/boss_app2/linux/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/boss_app2/linux/my_application.cc b/boss_app2/linux/my_application.cc new file mode 100644 index 0000000..90004d7 --- /dev/null +++ b/boss_app2/linux/my_application.cc @@ -0,0 +1,104 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "boss_app2"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "boss_app2"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); +} diff --git a/boss_app2/linux/my_application.h b/boss_app2/linux/my_application.h new file mode 100644 index 0000000..72271d5 --- /dev/null +++ b/boss_app2/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/boss_app2/macos/.gitignore b/boss_app2/macos/.gitignore new file mode 100644 index 0000000..746adbb --- /dev/null +++ b/boss_app2/macos/.gitignore @@ -0,0 +1,7 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/dgph +**/xcuserdata/ diff --git a/boss_app2/macos/Flutter/Flutter-Debug.xcconfig b/boss_app2/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 0000000..c2efd0b --- /dev/null +++ b/boss_app2/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/boss_app2/macos/Flutter/Flutter-Release.xcconfig b/boss_app2/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 0000000..c2efd0b --- /dev/null +++ b/boss_app2/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/boss_app2/macos/Flutter/GeneratedPluginRegistrant.swift b/boss_app2/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 0000000..9e793dc --- /dev/null +++ b/boss_app2/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,16 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import flutter_local_notifications +import flutter_native_timezone +import shared_preferences_macos + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) + FlutterNativeTimezonePlugin.register(with: registry.registrar(forPlugin: "FlutterNativeTimezonePlugin")) + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) +} diff --git a/boss_app2/macos/Runner.xcodeproj/project.pbxproj b/boss_app2/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..90ea18e --- /dev/null +++ b/boss_app2/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,572 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* boss_app2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "boss_app2.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* boss_app2.app */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* boss_app2.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/boss_app2/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/boss_app2/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/boss_app2/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/boss_app2/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/boss_app2/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..a919894 --- /dev/null +++ b/boss_app2/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/boss_app2/macos/Runner.xcworkspace/contents.xcworkspacedata b/boss_app2/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/boss_app2/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/boss_app2/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/boss_app2/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/boss_app2/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/boss_app2/macos/Runner/AppDelegate.swift b/boss_app2/macos/Runner/AppDelegate.swift new file mode 100644 index 0000000..d53ef64 --- /dev/null +++ b/boss_app2/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..a2ec33f --- /dev/null +++ b/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000..3c4935a Binary files /dev/null and b/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 0000000..ed4cc16 Binary files /dev/null and b/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100644 index 0000000..483be61 Binary files /dev/null and b/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100644 index 0000000..bcbf36d Binary files /dev/null and b/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100644 index 0000000..9c0a652 Binary files /dev/null and b/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100644 index 0000000..e71a726 Binary files /dev/null and b/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100644 index 0000000..8a31fe2 Binary files /dev/null and b/boss_app2/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/boss_app2/macos/Runner/Base.lproj/MainMenu.xib b/boss_app2/macos/Runner/Base.lproj/MainMenu.xib new file mode 100644 index 0000000..80e867a --- /dev/null +++ b/boss_app2/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/boss_app2/macos/Runner/Configs/AppInfo.xcconfig b/boss_app2/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 0000000..5716535 --- /dev/null +++ b/boss_app2/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = boss_app2 + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = com.example.bossApp2 + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2022 com.example. All rights reserved. diff --git a/boss_app2/macos/Runner/Configs/Debug.xcconfig b/boss_app2/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 0000000..36b0fd9 --- /dev/null +++ b/boss_app2/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/boss_app2/macos/Runner/Configs/Release.xcconfig b/boss_app2/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 0000000..dff4f49 --- /dev/null +++ b/boss_app2/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/boss_app2/macos/Runner/Configs/Warnings.xcconfig b/boss_app2/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 0000000..42bcbf4 --- /dev/null +++ b/boss_app2/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/boss_app2/macos/Runner/DebugProfile.entitlements b/boss_app2/macos/Runner/DebugProfile.entitlements new file mode 100644 index 0000000..dddb8a3 --- /dev/null +++ b/boss_app2/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/boss_app2/macos/Runner/Info.plist b/boss_app2/macos/Runner/Info.plist new file mode 100644 index 0000000..4789daa --- /dev/null +++ b/boss_app2/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/boss_app2/macos/Runner/MainFlutterWindow.swift b/boss_app2/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 0000000..2722837 --- /dev/null +++ b/boss_app2/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController.init() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/boss_app2/macos/Runner/Release.entitlements b/boss_app2/macos/Runner/Release.entitlements new file mode 100644 index 0000000..852fa1a --- /dev/null +++ b/boss_app2/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/boss_app2/pubspec.lock b/boss_app2/pubspec.lock new file mode 100644 index 0000000..1eba40b --- /dev/null +++ b/boss_app2/pubspec.lock @@ -0,0 +1,465 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.10" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.0" + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.8.2" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" + clock: + dependency: transitive + description: + name: clock + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.15.0" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + dbus: + dependency: transitive + description: + name: dbus + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.8" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.2" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.2" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + flutter_local_notifications: + dependency: "direct main" + description: + name: flutter_local_notifications + url: "https://pub.dartlang.org" + source: hosted + version: "9.2.0" + flutter_local_notifications_linux: + dependency: transitive + description: + name: flutter_local_notifications_linux + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.1+1" + flutter_local_notifications_platform_interface: + dependency: transitive + description: + name: flutter_local_notifications_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "5.0.0" + flutter_localizations: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + flutter_native_timezone: + dependency: "direct main" + description: + name: flutter_native_timezone + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + http: + dependency: "direct main" + description: + name: http + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.4" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" + image: + dependency: transitive + description: + name: image + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.1" + intl: + dependency: "direct main" + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.17.0" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.3" + lints: + dependency: transitive + description: + name: lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.11" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.3" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.7.0" + month_picker_dialog: + dependency: "direct main" + description: + name: month_picker_dialog + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.0" + nested: + dependency: transitive + description: + name: nested + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + path: + dependency: transitive + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.0" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.5" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.dartlang.org" + source: hosted + version: "4.4.0" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" + process: + dependency: transitive + description: + name: process + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.4" + provider: + dependency: "direct main" + description: + name: provider + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.2" + rxdart: + dependency: "direct main" + description: + name: rxdart + url: "https://pub.dartlang.org" + source: hosted + version: "0.26.0" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.12" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.10" + shared_preferences_ios: + dependency: transitive + description: + name: shared_preferences_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.9" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + shared_preferences_macos: + dependency: transitive + description: + name: shared_preferences_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.10.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.8" + timezone: + dependency: "direct main" + description: + name: timezone + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.0" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.8" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0" + xml: + dependency: transitive + description: + name: xml + url: "https://pub.dartlang.org" + source: hosted + version: "5.3.1" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" +sdks: + dart: ">=2.16.0-134.1.beta <3.0.0" + flutter: ">=2.5.0" diff --git a/boss_app2/pubspec.yaml b/boss_app2/pubspec.yaml new file mode 100644 index 0000000..2f95534 --- /dev/null +++ b/boss_app2/pubspec.yaml @@ -0,0 +1,109 @@ +name: boss_app2 +description: A new Flutter project. + +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +version: 1.0.0+1 + +environment: + sdk: ">=2.16.0-134.1.beta <3.0.0" + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.2 + # flutter_local_notifications: ^7.0.0 + flutter_local_notifications: ^9.2.0 + flutter_native_timezone: ^2.0.0 + http: ^0.13.4 + intl: ^0.17.0 + month_picker_dialog: ^0.4.0 + provider: ^6.0.2 + rxdart: ^0.26.0 + # rxdart: ^0.27.3 + shared_preferences: ^2.0.12 + timezone: ^0.8.0 + # timezone: ^0.7.0 + +dev_dependencies: + flutter_test: + sdk: flutter + + flutter_launcher_icons: "^0.9.2" + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^1.0.0 + +flutter_icons: + image_path: "assets/iconnya.png" + android: true + ios: true + + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/boss_app2/test/widget_test.dart b/boss_app2/test/widget_test.dart new file mode 100644 index 0000000..8c9279e --- /dev/null +++ b/boss_app2/test/widget_test.dart @@ -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 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:boss_app2/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); + }); +} diff --git a/boss_app2/web/favicon.png b/boss_app2/web/favicon.png new file mode 100644 index 0000000..8aaa46a Binary files /dev/null and b/boss_app2/web/favicon.png differ diff --git a/boss_app2/web/icons/Icon-192.png b/boss_app2/web/icons/Icon-192.png new file mode 100644 index 0000000..b749bfe Binary files /dev/null and b/boss_app2/web/icons/Icon-192.png differ diff --git a/boss_app2/web/icons/Icon-512.png b/boss_app2/web/icons/Icon-512.png new file mode 100644 index 0000000..88cfd48 Binary files /dev/null and b/boss_app2/web/icons/Icon-512.png differ diff --git a/boss_app2/web/icons/Icon-maskable-192.png b/boss_app2/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000..eb9b4d7 Binary files /dev/null and b/boss_app2/web/icons/Icon-maskable-192.png differ diff --git a/boss_app2/web/icons/Icon-maskable-512.png b/boss_app2/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000..d69c566 Binary files /dev/null and b/boss_app2/web/icons/Icon-maskable-512.png differ diff --git a/boss_app2/web/index.html b/boss_app2/web/index.html new file mode 100644 index 0000000..26f3060 --- /dev/null +++ b/boss_app2/web/index.html @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + boss_app2 + + + + + + + diff --git a/boss_app2/web/manifest.json b/boss_app2/web/manifest.json new file mode 100644 index 0000000..7bcb575 --- /dev/null +++ b/boss_app2/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "boss_app2", + "short_name": "boss_app2", + "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" + } + ] +} diff --git a/boss_app2/windows/.gitignore b/boss_app2/windows/.gitignore new file mode 100644 index 0000000..d492d0d --- /dev/null +++ b/boss_app2/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/boss_app2/windows/CMakeLists.txt b/boss_app2/windows/CMakeLists.txt new file mode 100644 index 0000000..78c4854 --- /dev/null +++ b/boss_app2/windows/CMakeLists.txt @@ -0,0 +1,95 @@ +cmake_minimum_required(VERSION 3.14) +project(boss_app2 LANGUAGES CXX) + +set(BINARY_NAME "boss_app2") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() + +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/boss_app2/windows/flutter/CMakeLists.txt b/boss_app2/windows/flutter/CMakeLists.txt new file mode 100644 index 0000000..b2e4bd8 --- /dev/null +++ b/boss_app2/windows/flutter/CMakeLists.txt @@ -0,0 +1,103 @@ +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/boss_app2/windows/flutter/generated_plugin_registrant.cc b/boss_app2/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..8b6d468 --- /dev/null +++ b/boss_app2/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void RegisterPlugins(flutter::PluginRegistry* registry) { +} diff --git a/boss_app2/windows/flutter/generated_plugin_registrant.h b/boss_app2/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..dc139d8 --- /dev/null +++ b/boss_app2/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/boss_app2/windows/flutter/generated_plugins.cmake b/boss_app2/windows/flutter/generated_plugins.cmake new file mode 100644 index 0000000..4d10c25 --- /dev/null +++ b/boss_app2/windows/flutter/generated_plugins.cmake @@ -0,0 +1,15 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) diff --git a/boss_app2/windows/runner/CMakeLists.txt b/boss_app2/windows/runner/CMakeLists.txt new file mode 100644 index 0000000..de2d891 --- /dev/null +++ b/boss_app2/windows/runner/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) +apply_standard_settings(${BINARY_NAME}) +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/boss_app2/windows/runner/Runner.rc b/boss_app2/windows/runner/Runner.rc new file mode 100644 index 0000000..5dc700d --- /dev/null +++ b/boss_app2/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#ifdef FLUTTER_BUILD_NUMBER +#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER +#else +#define VERSION_AS_NUMBER 1,0,0 +#endif + +#ifdef FLUTTER_BUILD_NAME +#define VERSION_AS_STRING #FLUTTER_BUILD_NAME +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "boss_app2" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "boss_app2" "\0" + VALUE "LegalCopyright", "Copyright (C) 2022 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "boss_app2.exe" "\0" + VALUE "ProductName", "boss_app2" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/boss_app2/windows/runner/flutter_window.cpp b/boss_app2/windows/runner/flutter_window.cpp new file mode 100644 index 0000000..b43b909 --- /dev/null +++ b/boss_app2/windows/runner/flutter_window.cpp @@ -0,0 +1,61 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/boss_app2/windows/runner/flutter_window.h b/boss_app2/windows/runner/flutter_window.h new file mode 100644 index 0000000..6da0652 --- /dev/null +++ b/boss_app2/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/boss_app2/windows/runner/main.cpp b/boss_app2/windows/runner/main.cpp new file mode 100644 index 0000000..18d08e8 --- /dev/null +++ b/boss_app2/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"boss_app2", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/boss_app2/windows/runner/resource.h b/boss_app2/windows/runner/resource.h new file mode 100644 index 0000000..66a65d1 --- /dev/null +++ b/boss_app2/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/boss_app2/windows/runner/resources/app_icon.ico b/boss_app2/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000..c04e20c Binary files /dev/null and b/boss_app2/windows/runner/resources/app_icon.ico differ diff --git a/boss_app2/windows/runner/runner.exe.manifest b/boss_app2/windows/runner/runner.exe.manifest new file mode 100644 index 0000000..c977c4a --- /dev/null +++ b/boss_app2/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/boss_app2/windows/runner/utils.cpp b/boss_app2/windows/runner/utils.cpp new file mode 100644 index 0000000..d19bdbb --- /dev/null +++ b/boss_app2/windows/runner/utils.cpp @@ -0,0 +1,64 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/boss_app2/windows/runner/utils.h b/boss_app2/windows/runner/utils.h new file mode 100644 index 0000000..3879d54 --- /dev/null +++ b/boss_app2/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/boss_app2/windows/runner/win32_window.cpp b/boss_app2/windows/runner/win32_window.cpp new file mode 100644 index 0000000..c10f08d --- /dev/null +++ b/boss_app2/windows/runner/win32_window.cpp @@ -0,0 +1,245 @@ +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/boss_app2/windows/runner/win32_window.h b/boss_app2/windows/runner/win32_window.h new file mode 100644 index 0000000..17ba431 --- /dev/null +++ b/boss_app2/windows/runner/win32_window.h @@ -0,0 +1,98 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/readme.md b/readme.md deleted file mode 100644 index ca51ca6..0000000 --- a/readme.md +++ /dev/null @@ -1,9 +0,0 @@ -Aplikasi Track Stok Barang dan Penjualan - -This is the desktop app of stock tracking system. -Using electron to convert the HTML, CSS, and JavaScript into a desktop app. -If you ask about the "customurl://" , it was for checking if the XAMPP is running or not. -If XAMPP is not running, then the app will automatically start the XAMPP. -****************************************************** - -Created By Kicap Karan www.facebook.com/kicap.karan \ No newline at end of file