Compare commits

..

92 Commits

Author SHA1 Message Date
57508fe17e Refactor routine creation logic and add new dropdown events 2025-06-15 13:29:32 +03:00
994e9f4e57 Revert "formatted all files." (#250)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

Reverted formatting PR.
This reverts commit 04250ebc98.

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [x] 🗑️ Chore
2025-06-12 16:09:32 +03:00
c642ba2644 Revert "formatted all files."
This reverts commit 04250ebc98.
2025-06-12 16:04:49 +03:00
218f43bacb Formatting all files (#249)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

Formatted all files in the repository.

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [x] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-12 15:40:34 +03:00
04250ebc98 formatted all files. 2025-06-12 15:33:32 +03:00
29959f567e upgrade-flutter-version-in-deployment-actions. (#248)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

<!--- Describe your changes in detail -->

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [x] 🗑️ Chore
2025-06-12 15:07:12 +03:00
fe3b5263a3 upgrade to not using webkit renderer command in ci/cd actions because it is deprecated. 2025-06-12 15:04:33 +03:00
c3a0c48501 Merge branch 'dev' of https://github.com/SyncrowIOT/web into upgrade-flutter-version-in-deployment-actions 2025-06-12 14:58:36 +03:00
5203491d15 upgrade-flutter-version-in-deployment-actions. 2025-06-12 14:57:55 +03:00
c379cfaed0 Update pr-check.yml (#247)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

Upgrade pr-check GitHub action flutter version to `3.32.1`.

## Type of Change

- [ ]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [x] 🗑️ Chore
2025-06-12 14:55:55 +03:00
d971479256 Deleted all unnecessary build targets (#246)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

Deleted iOS, Android, MacOS, Linux and Windows build targets, since
they're not needed for this repository. If they were ever needed we can
create new ones.

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [x] 🗑️ Chore
2025-06-12 14:55:45 +03:00
7109f3712a Update pr-check.yml 2025-06-12 14:50:50 +03:00
70a94bb1c1 Merge branch 'dev' of https://github.com/SyncrowIOT/web into deletes_unnecessary_build_targets 2025-06-12 14:41:14 +03:00
88480142e1 Very good analysis (#245)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

Migrated lints to use `very_good_analysis`.

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [x] 🗑️ Chore
2025-06-12 14:39:46 +03:00
1a2378df6e Deleted all unnecessary build targets 2025-06-12 14:35:54 +03:00
e867c29086 use very_good_analysis lints. 2025-06-12 14:31:08 +03:00
a3b427c570 fix the save button by removing deleted items from spaces then return… (#244)
… all other elements status to unchanged

<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket

[SP-1735](https://syncrow.atlassian.net/browse/SP-1735?atlOrigin=eyJpIjoiZTI5OTQ5NzNkYWIyNDQ5OTg5YWFkYjRhMTg5NmYxMDkiLCJwIjoiamlyYS1zbGFjay1pbnQifQ)

## Description

now whenever u save then save button vanish until u make another chages

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore 


[SP-1735]:
https://syncrow.atlassian.net/browse/SP-1735?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2025-06-12 14:27:06 +03:00
0b0e235f26 fix the save button by removing deleted items from spaces then return all other elements status to unchanged 2025-06-12 14:13:25 +03:00
c250fb4469 Sp 1702 fe when we click on edit button for a space and click ok without editing the save button is appearing (#243)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket
[sp:1702 fix Bug](https://syncrow.atlassian.net/browse/SP-1702)

## Description

fix the issue when nothing edited save button not appears
## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-11 16:58:34 +03:00
59ac1bd74d Disable tap action on Community Structure when in specific states (#242)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->


## Description

<!--- Describe your changes in detail -->
Disable tap action on Community Structure when in specific states
## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-11 16:48:10 +03:00
bac1450c2b User can't Add a space if he adds a device with a tag manually/1689 (#240)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket

(https://syncrow.atlassian.net/browse/SP-0000)](https://syncrow.atlassian.net/browse/SP-1689)](https://syncrow.atlassian.net/browse/SP-1689)

## Description

when adding device and assign new manual tag (without uuid) ok button
doesnt response

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-11 16:47:15 +03:00
889461db7d Enhance device management UI with improved padding and SVG icon integ… (#241)
…ration

<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->



## Description

<!--- Describe your changes in detail -->

Enhance device setting ui 

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-11 16:47:00 +03:00
27dbcb26f1 use function to fix bug 2025-06-11 16:35:34 +03:00
0c5db9dfeb add bool function to space model if no changes made on object 2025-06-11 16:35:19 +03:00
1393a15eca Disable tap action on Community Structure when in specific states 2025-06-11 16:02:40 +03:00
3c6f88b245 Sp 1601 fe community and space dialog redesign in the routine tab (#236)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket
[SP-1601](https://syncrow.atlassian.net/browse/SP-1601)

## Description

<!--- Describe your changes in detail -->
redesign community and space dialog and On Access management and Devices
Management Pages Clicking the Reset button should reset the table and
buttons not refresh the Page

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [x]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore 


[SP-1601]:
https://syncrow.atlassian.net/browse/SP-1601?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2025-06-11 14:46:35 +03:00
0b92abff26 Merge branch 'dev' into SP-1601-FE-Community-and-Space-Dialog-Redesign-in-the-routine-tab 2025-06-11 14:18:42 +03:00
fc86042af7 Implement SpaceTreeDropdownBloc for improved state management in SpaceTreeDropdown; refactor dropdown logic and event handling. 2025-06-11 14:14:21 +03:00
cd6bf32aed fix bug /non uuid assign tag to be accepted 2025-06-11 14:00:15 +03:00
e81b9a853e Space managment refactoring merge (#239) with dev
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket
[SP-0000](https://syncrow.atlassian.net/browse/SP-0000)

## Description
merge latest working updates
<!--- Describe your changes in detail -->

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [x]  Breaking change (fix or feature that would cause existing
functionality to change)
- [x] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-11 13:08:52 +03:00
f415aa1676 Delete unused File 2025-06-11 12:57:00 +03:00
08f8c3c79a Delete unused File 2025-06-11 12:56:28 +03:00
329a4ef027 Delete 2025-06-11 12:55:54 +03:00
940b179686 Delete unused file 2025-06-11 12:55:14 +03:00
5ddfb47977 Delete unused File 2025-06-11 12:54:38 +03:00
2a5d602e94 Merge branch 'dev' into space_managment_refactoring 2025-06-11 11:12:52 +03:00
5d6747056e Update button behavior in DeviceManagementPage based on routineTab state (#238)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket
[SP-1605](https://syncrow.atlassian.net/browse/SP-1605)

## Description

<!--- Describe your changes in detail -->
Disable Clicking on Active Tabs in Devices and Spaces Management Views
## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore 


[SP-1605]:
https://syncrow.atlassian.net/browse/SP-1605?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2025-06-11 10:56:36 +03:00
8a274af7be Update button behavior in DeviceManagementPage based on routineTab state 2025-06-11 10:47:59 +03:00
316c3bd8a7 Build main structure (#214) merge
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket
[SP-1637](https://syncrow.atlassian.net/browse/SP-1637)

## Description

seperate widgets and fix plustbutton hover bug and save on pressing ok
when adding subspaces&&tags can added when unfocus textfield

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [x] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore 


[SP-1637]:
https://syncrow.atlassian.net/browse/SP-1637?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2025-06-11 10:46:59 +03:00
d66921c615 Merge remote-tracking branch 'origin/dev' into SP-1601-FE-Community-and-Space-Dialog-Redesign-in-the-routine-tab 2025-06-11 10:08:47 +03:00
aa3b79bdaf stop fetching tags onBlank Event 2025-06-10 16:34:49 +03:00
0e31a3ea96 no need to fetch use info in init state of homepage and agreement dialog 2025-06-10 16:33:33 +03:00
fd192894cd stop calling initEvent for spactree bloc inside homeBloc 2025-06-10 16:32:33 +03:00
f7f3843fa7 Enhance device management UI with improved padding and SVG icon integration 2025-06-10 16:29:14 +03:00
692c9e7792 comment (SpaceModelLinking && Or)Widgets cuz no need for spaceModel for now&& fix the delete devices from subSpaces to keep in main space not to get deleted 2025-06-10 15:11:33 +03:00
08a9a5c71f comment the tab of spaceModel to prevent routing there 2025-06-10 15:08:50 +03:00
7eb1d5b0b0 comment listSpace func which calls SpaceModels that suspended for now 2025-06-10 15:07:32 +03:00
0d5734a236 use tag instead of UpdatedTagModel cuz no need for updatedmodel anymore&&key should be spaces with S 2025-06-10 15:06:31 +03:00
a1b20078a3 Refactor AccessBloc to emit filtered data instead of fetching; clean up device search filters for improved readability. 2025-06-10 12:10:47 +03:00
ed06a760d2 change spaceHint and size 2025-06-10 11:41:42 +03:00
e22bab00d9 just format code in assign tag bloc 2025-06-10 10:27:08 +03:00
d2a2d391e0 send subspaces with onSave in okCancel inside subspace dialog as parameters 2025-06-10 10:19:48 +03:00
1d30c753f5 edit tag model keys to integrate with backend 2025-06-10 10:08:49 +03:00
ca02de2093 edit subspace model to fix keys and integrate with backend 2025-06-10 10:07:26 +03:00
8f7bfa984b edit spacemodel to use the right keys to integrate with backend 2025-06-10 10:06:36 +03:00
8e9278c93c edits with faris and main task to fix loading state forever and prevent rethrow exceptions without catching them 2025-06-10 10:05:50 +03:00
15d3a05553 assign tag dropDown now show all Tags without condition 2025-06-10 10:03:32 +03:00
662fe211eb Refactor HomeBloc and GarageDoorBloc event handling; update CreateNewRoutinesDialog to use SpaceTreeDropdown; add settings button SVG. 2025-06-09 22:55:00 +03:00
c6b55cb28b Sp 1594 device location api integration (#216)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket
[SP-1594](https://syncrow.atlassian.net/browse/SP-1594)

## Description

1. Implemented `Bloc` and `Services` to integrate the device location
into the side panel of the AQI Analytics module.
2. Fixed bugs in side panel caused by `Expanded` widgets.

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x]  New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore 


[SP-1594]:
https://syncrow.atlassian.net/browse/SP-1594?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2025-06-04 16:41:08 +03:00
bfd8e964f7 SP-1665-FE-Return-a-readable-error-when-a-connection-error-Exception-… (#233)
…occurs-on-the-charts.

<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket
[SP-1665](https://syncrow.atlassian.net/browse/SP-1665)

## Description

Returns a readable error when an analytics api fails.

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore 


[SP-1665]:
https://syncrow.atlassian.net/browse/SP-1665?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2025-06-04 16:40:25 +03:00
08725201d5 Dev ci/cd enhancements (#234)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

Pulled CI/CD changes from `main` branch into `dev` branch.

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [x] 🗑️ Chore
2025-06-04 16:10:00 +03:00
7fe34c61b2 correctly fetch energy management data using spaceUuid. (#235)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket
[SP-1495](https://syncrow.atlassian.net/browse/SP-1495)

## Description

correctly fetch energy management data using `spaceUuid`.

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)

[SP-1495]:
https://syncrow.atlassian.net/browse/SP-1495?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2025-06-04 16:09:10 +03:00
0c6e4fed80 correctly fetch energy management data using spaceUuid. 2025-06-04 15:09:40 +03:00
69c23525ba Merge branch 'dev' of https://github.com/SyncrowIOT/web into SP-1665-FE-Return-a-readable-error-when-a-connection-error-Exception-occurs-on-the-charts 2025-06-04 14:49:48 +03:00
3e32968209 Update pull_request_template.md 2025-06-04 14:47:35 +03:00
beb5239c4f enhanced ci/cd by not running the deply jobs on the PR itself, and now we only deploy when we merged a PR to dev or main, and created a separate GitHub action that only builds and install dependencies, which only runs on the PR itself. 2025-06-04 14:47:35 +03:00
3a98f71ff3 SP-1665-FE-Return-a-readable-error-when-a-connection-error-Exception-occurs-on-the-charts. 2025-06-04 14:42:41 +03:00
ad8e06ac40 Sp 1457 fe edit popup buttons labels to be the same as the design (#231)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket
[SP-1457](https://syncrow.atlassian.net/browse/SP-1457)

## Description

<!--- Describe your changes in detail -->
Edit popup buttons labels to be the same as the design and change
setting icon

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [X]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore 


[SP-1457]:
https://syncrow.atlassian.net/browse/SP-1457?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2025-06-04 11:05:37 +03:00
5f8eb9de06 Add settings button SVG and refactor settings icon implementation in dynamic table 2025-06-04 10:32:31 +03:00
8e8fdf0fc6 Rename dialog buttons for clarity: 'Cancel' to 'Back' and 'Confirm' to 'Save' 2025-06-04 09:26:56 +03:00
a1d7457065 Test commit with updated user 2025-05-29 14:34:15 +03:00
c99b32fb81 cancel direction 2025-05-28 06:50:04 -05:00
321df401fd comment interceptor cuz it is crashing app 2025-05-28 01:56:57 -05:00
ee244fa5ed use textfield controller from constructor 2025-05-28 01:48:37 -05:00
1db069e9a5 use devicePart in main widget 2025-05-28 01:21:06 -05:00
cf9bafef4d add devices part widget 2025-05-28 01:20:31 -05:00
2c73dd6c31 call the new widgets 2025-05-28 00:42:05 -05:00
6ec20e2d72 seperate subspace part into widget 2025-05-28 00:41:53 -05:00
4feae9ad87 seperate spacemodel linking into widget 2025-05-28 00:41:33 -05:00
52046909d5 seperate textfield of the space name 2025-05-28 00:41:01 -05:00
fc81555be3 seperate iconchoose widget in create space dialog 2025-05-28 00:40:34 -05:00
8967852ca8 seperate assign tag dialog to widgets 2025-05-27 06:01:25 -05:00
a87e79878b add ok_candel row of buttons in seperated widget also text field widget 2025-05-27 05:32:42 -05:00
056e7372e0 use assign table as widget 2025-05-27 01:15:30 -05:00
d69d867120 use assign_tag_dialog_widgetwidget 2025-05-26 06:27:48 -05:00
644fe56478 seperaate UI into widgets 2025-05-26 06:12:24 -05:00
766a39f161 use selected model in add device event 2025-05-26 06:11:48 -05:00
c97dd40b05 add toSelected function to convert from product to selectedProduct 2025-05-26 06:11:06 -05:00
0b65c58947 fix add subspace bugs and plusButton widget 2025-05-26 02:45:58 -05:00
e0951aa13d add interceptor to print request and response 2025-05-23 08:52:53 -05:00
9e8ebf3768 no need for models and blocs for now 2025-05-23 07:52:21 -05:00
b593e75c67 build main structure and build data layer and space managment bloc 2025-05-23 02:17:23 -05:00
207 changed files with 2949 additions and 6738 deletions

View File

@ -7,11 +7,7 @@
--> -->
## Jira Ticket ## Jira Ticket
<!-- Add your Jira ticket number as a link (e.g., [PROJ-123](https://jira.company.com/browse/PROJ-123)) --> [SP-0000](https://syncrow.atlassian.net/browse/SP-0000)
## Status
**READY/IN DEVELOPMENT/HOLD**
## Description ## Description
@ -27,4 +23,4 @@
- [ ] 🧹 Code refactor - [ ] 🧹 Code refactor
- [ ] ✅ Build configuration change - [ ] ✅ Build configuration change
- [ ] 📝 Documentation - [ ] 📝 Documentation
- [ ] 🗑️ Chore - [ ] 🗑️ Chore

View File

@ -4,10 +4,6 @@ on:
push: push:
branches: branches:
- main - main
pull_request:
types: [opened, synchronize, reopened, closed]
branches:
- main
jobs: jobs:
build_and_deploy_job: build_and_deploy_job:
@ -25,13 +21,13 @@ jobs:
- name: Set up Flutter - name: Set up Flutter
uses: subosito/flutter-action@v2 uses: subosito/flutter-action@v2
with: with:
flutter-version: '3.27.3' # Specify the Flutter version you want to use flutter-version: '3.32.1' # Specify the Flutter version you want to use
- name: Install dependencies - name: Install dependencies
run: flutter pub get run: flutter pub get
- name: Build Flutter Web App - name: Build Flutter Web App
run: flutter build web --web-renderer canvaskit -t lib/main.dart run: flutter build web --release -t lib/main.dart
- name: Build And Deploy - name: Build And Deploy
id: builddeploy id: builddeploy

View File

@ -4,18 +4,12 @@ on:
push: push:
branches: branches:
- dev - dev
pull_request:
types: [opened, synchronize, reopened, closed]
branches:
- dev
jobs: jobs:
build_and_deploy_job: build_and_deploy_job:
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Build and Deploy Job name: Build and Deploy Job
steps: steps:
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
@ -25,13 +19,13 @@ jobs:
- name: Set up Flutter - name: Set up Flutter
uses: subosito/flutter-action@v2 uses: subosito/flutter-action@v2
with: with:
flutter-version: '3.27.3' # Specify the Flutter version you want to use flutter-version: '3.32.1' # Specify the Flutter version you want to use
- name: Install dependencies - name: Install dependencies
run: flutter pub get run: flutter pub get
- name: Build Flutter Web App - name: Build Flutter Web App
run: flutter build web --web-renderer canvaskit -t lib/main_dev.dart run: flutter build web --release -t lib/main_dev.dart
- name: Build And Deploy - name: Build And Deploy
id: builddeploy id: builddeploy

29
.github/workflows/pr-check.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: Pull Request Check
on:
pull_request:
branches:
- dev
- main
jobs:
setup_flutter:
runs-on: ubuntu-latest
name: Setup Flutter and Dependencies
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
submodules: true
lfs: false
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.32.1'
- name: Install dependencies
run: flutter pub get
- name: Run Flutter Build
run: flutter build web --release -t lib/main_dev.dart

View File

@ -1,33 +1,32 @@
# This file configures the analyzer, which statically analyzes Dart code to include: package:very_good_analysis/analysis_options.yaml
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
analyzer: analyzer:
errors: errors:
constant_identifier_names: ignore strict_raw_type: warning
overridden_fields: ignore argument_type_not_assignable: warning
include: package:flutter_lints/flutter.yaml invalid_assignment: warning
return_of_invalid_type: warning
return_of_invalid_type_from_closure: warning
list_element_type_not_assignable: warning
for_in_of_invalid_type: warning
cast_nullable_to_non_nullable: warning
non_bool_condition: warning
field_initializer_not_assignable: warning
non_bool_negation_expression: warning
non_bool_operand: warning
linter: linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at https://dart.dev/lints.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules: rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule prefer_single_quotes: true
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule avoid_print: false
prefer_const_constructors: true public_member_api_docs: false
sort_pub_dependencies: false
# Additional information about this file can be found at one_member_abstracts: false
# https://dart.dev/guides/language/analysis-options prefer_int_literals: false
sort_constructors_first: false
avoid_redundant_argument_values: false
always_put_required_named_parameters_first: false
unnecessary_breaks: false
avoid_catches_without_on_clauses: false
cascade_invocations: false
overridden_fields: false

13
android/.gitignore vendored
View File

@ -1,13 +0,0 @@
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

View File

@ -1,71 +0,0 @@
plugins {
id "com.android.application"
// START: FlutterFire Configuration
id 'com.google.gms.google-services'
id 'com.google.firebase.crashlytics'
// END: FlutterFire Configuration
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
android {
namespace "com.example.syncrow_web"
compileSdk flutter.compileSdkVersion
ndkVersion flutter.ndkVersion
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.syncrow_web"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
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 {}

View File

@ -1,68 +0,0 @@
{
"project_info": {
"project_number": "427332280600",
"firebase_url": "https://test2-8a3d2-default-rtdb.firebaseio.com",
"project_id": "test2-8a3d2",
"storage_bucket": "test2-8a3d2.firebasestorage.app"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:427332280600:android:550f67441246cb1a0c7e6d",
"android_client_info": {
"package_name": "com.example.syncrow.app"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyA5qOErxdm0zJmoHIB0TixfebYEsNRpwV0"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:427332280600:android:bb6047adeeb80fb00c7e6d",
"android_client_info": {
"package_name": "com.example.syncrow_application"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyA5qOErxdm0zJmoHIB0TixfebYEsNRpwV0"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:427332280600:android:2bc36fbe82994a3e0c7e6d",
"android_client_info": {
"package_name": "com.example.syncrow_web"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyA5qOErxdm0zJmoHIB0TixfebYEsNRpwV0"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}

View File

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

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

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

View File

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

View File

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

View File

@ -1,18 +0,0 @@
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

View File

@ -1,3 +0,0 @@
org.gradle.jvmargs=-Xmx4G
android.useAndroidX=true
android.enableJetifier=true

View File

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

View File

@ -1,30 +0,0 @@
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}
settings.ext.flutterSdkPath = flutterSdkPath()
includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "7.3.0" apply false
// START: FlutterFire Configuration
id "com.google.gms.google-services" version "4.3.15" apply false
id "com.google.firebase.crashlytics" version "2.8.1" apply false
// END: FlutterFire Configuration
id "org.jetbrains.kotlin.android" version "1.7.10" apply false
}
include ":app"

View File

@ -0,0 +1,24 @@
<svg width="40" height="26" viewBox="0 0 40 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_9292_1537)">
<rect x="3" y="3" width="34" height="20" rx="10" fill="#F5F6F7"/>
<g clip-path="url(#clip0_9292_1537)">
<path d="M20.4393 20H19.5607C18.85 20 18.2718 19.4218 18.2718 18.7112V18.414C17.9697 18.3174 17.6762 18.1956 17.3942 18.0497L17.1835 18.2603C16.6733 18.7711 15.8561 18.7562 15.3607 18.2601L14.7397 17.6391C14.2434 17.1434 14.2291 16.3264 14.7398 15.8163L14.9503 15.6058C14.8044 15.3238 14.6826 15.0303 14.586 14.7281H14.2888C13.5782 14.7281 13 14.15 13 13.4393V12.5607C13 11.85 13.5782 11.2719 14.2888 11.2719H14.586C14.6826 10.9697 14.8044 10.6762 14.9503 10.3942L14.7397 10.1836C14.2293 9.67374 14.2434 8.85666 14.7399 8.36072L15.3609 7.73969C15.8574 7.24247 16.6745 7.23006 17.1838 7.73986L17.3942 7.95032C17.6762 7.80441 17.9698 7.68257 18.2719 7.58602V7.28879C18.2719 6.57816 18.85 6 19.5607 6H20.4393C21.15 6 21.7281 6.57816 21.7281 7.28879V7.58605C22.0302 7.68257 22.3238 7.80441 22.6058 7.95035L22.8164 7.73969C23.3266 7.22886 24.1439 7.24384 24.6393 7.73988L25.2603 8.36086C25.7566 8.85657 25.7708 9.67358 25.2601 10.1837L25.0497 10.3942C25.1956 10.6762 25.3174 10.9697 25.414 11.2719H25.7112C26.4218 11.2719 27 11.85 27 12.5607V13.4393C27 14.15 26.4218 14.7281 25.7112 14.7281H25.414C25.3174 15.0303 25.1956 15.3238 25.0497 15.6058L25.2603 15.8164C25.7707 16.3263 25.7566 17.1434 25.2601 17.6393L24.6391 18.2603C24.1426 18.7576 23.3255 18.77 22.8162 18.2602L22.6058 18.0497C22.3238 18.1956 22.0302 18.3175 21.7281 18.414V18.7113C21.7281 19.4218 21.15 20 20.4393 20ZM17.5313 17.1882C17.9231 17.4199 18.3447 17.595 18.7845 17.7085C18.9656 17.7552 19.0922 17.9185 19.0922 18.1056V18.7112C19.0922 18.9695 19.3024 19.1797 19.5607 19.1797H20.4393C20.6976 19.1797 20.9078 18.9695 20.9078 18.7112V18.1056C20.9078 17.9185 21.0344 17.7552 21.2155 17.7085C21.6553 17.595 22.0769 17.4199 22.4687 17.1882C22.6299 17.0929 22.8351 17.1188 22.9675 17.2513L23.3965 17.6803C23.5815 17.8654 23.8785 17.8611 24.0589 17.6805L24.6803 17.059C24.8603 16.8793 24.8663 16.5822 24.6805 16.3966L24.2513 15.9675C24.1189 15.8351 24.093 15.6298 24.1883 15.4687C24.42 15.0769 24.595 14.6553 24.7085 14.2155C24.7552 14.0344 24.9186 13.9078 25.1056 13.9078H25.7112C25.9695 13.9078 26.1797 13.6977 26.1797 13.4394V12.5607C26.1797 12.3024 25.9695 12.0922 25.7112 12.0922H25.1056C24.9186 12.0922 24.7552 11.9657 24.7085 11.7846C24.595 11.3447 24.42 10.9231 24.1883 10.5314C24.093 10.3702 24.1189 10.165 24.2513 10.0326L24.6803 9.60358C24.8658 9.41835 24.8609 9.1214 24.6805 8.94118L24.0591 8.31979C23.879 8.13943 23.5819 8.13415 23.3967 8.31962L22.9676 8.74879C22.8352 8.88121 22.6299 8.90713 22.4687 8.81181C22.077 8.58013 21.6553 8.4051 21.2155 8.2916C21.0344 8.24487 20.9079 8.08152 20.9079 7.89446V7.28879C20.9079 7.03048 20.6977 6.82031 20.4394 6.82031H19.5607C19.3024 6.82031 19.0922 7.03048 19.0922 7.28879V7.8944C19.0922 8.08146 18.9657 8.24481 18.7845 8.29154C18.3447 8.40505 17.9231 8.58007 17.5314 8.81176C17.3701 8.90705 17.1649 8.88113 17.0325 8.74873L16.6036 8.31973C16.4186 8.13456 16.1216 8.13886 15.9412 8.31954L15.3197 8.94096C15.1398 9.12071 15.1337 9.41775 15.3196 9.60336L15.7487 10.0325C15.8811 10.1649 15.9071 10.3702 15.8118 10.5313C15.5801 10.9231 15.4051 11.3447 15.2916 11.7845C15.2448 11.9656 15.0815 12.0922 14.8944 12.0922H14.2888C14.0305 12.0922 13.8203 12.3024 13.8203 12.5607V13.4393C13.8203 13.6976 14.0305 13.9078 14.2888 13.9078H14.8944C15.0815 13.9078 15.2448 14.0344 15.2915 14.2155C15.405 14.6553 15.5801 15.0769 15.8117 15.4686C15.907 15.6298 15.8811 15.8351 15.7487 15.9675L15.3197 16.3965C15.1343 16.5817 15.1391 16.8786 15.3195 17.0589L15.9409 17.6802C16.121 17.8606 16.4181 17.8659 16.6033 17.6804L17.0325 17.2512C17.13 17.1537 17.333 17.0709 17.5313 17.1882Z" fill="#023DFE" fill-opacity="0.7"/>
<path d="M19.9992 16.0461C18.3196 16.0461 16.9531 14.6796 16.9531 13C16.9531 11.3204 18.3196 9.95391 19.9992 9.95391C21.6789 9.95391 23.0453 11.3204 23.0453 13C23.0453 14.6796 21.6789 16.0461 19.9992 16.0461ZM19.9992 10.7742C18.7719 10.7742 17.7734 11.7727 17.7734 13C17.7734 14.2273 18.7719 15.2258 19.9992 15.2258C21.2265 15.2258 22.225 14.2273 22.225 13C22.225 11.7727 21.2265 10.7742 19.9992 10.7742Z" fill="#023DFE" fill-opacity="0.7"/>
</g>
</g>
<defs>
<filter id="filter0_d_9292_1537" x="0" y="0" width="40" height="26" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="1.5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_9292_1537"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_9292_1537" result="shape"/>
</filter>
<clipPath id="clip0_9292_1537">
<rect width="14" height="14" fill="white" transform="translate(13 6)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 5.0 KiB

34
ios/.gitignore vendored
View File

@ -1,34 +0,0 @@
**/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

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>12.0</string>
</dict>
</plist>

View File

@ -1,2 +0,0 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"

View File

@ -1,2 +0,0 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"

View File

@ -1,44 +0,0 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '12.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end

View File

@ -1,36 +0,0 @@
PODS:
- Flutter (1.0.0)
- flutter_secure_storage (6.0.0):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
DEPENDENCIES:
- Flutter (from `Flutter`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
EXTERNAL SOURCES:
Flutter:
:path: Flutter
flutter_secure_storage:
:path: ".symlinks/plugins/flutter_secure_storage/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
SPEC CHECKSUMS:
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796
COCOAPODS: 1.15.2

View File

@ -1,751 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
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 */; };
E44A9405B1EB1B638DD05A58 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7ABF0EC746A2D686A0ED574F /* Pods_RunnerTests.framework */; };
F2A3345EC3021060731668D3 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = B14AB50E8716720E10D074BD /* GoogleService-Info.plist */; };
FF49F60EC38658783D8D66DA /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2AFAE479A87ECDEBD5D6EB30 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
proxyType = 1;
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
remoteInfo = Runner;
};
/* End PBXContainerItemProxy 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 = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
22428D486F110EE0B969469D /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
253C5EA6840355311DB030EA /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
2AFAE479A87ECDEBD5D6EB30 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
2C0D722D2ED971BF672D18D5 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
544621C7727C798253BAB2C8 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7ABF0EC746A2D686A0ED574F /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
877FDC97D8B87080E35B3EB7 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
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 = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
B14AB50E8716720E10D074BD /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = "<group>"; };
D3AD250AADBF93406007C9EB /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
759A57780A409ED209817654 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
E44A9405B1EB1B638DD05A58 /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FF49F60EC38658783D8D66DA /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
1454C118FFCECEEDF59152D2 /* Pods */ = {
isa = PBXGroup;
children = (
253C5EA6840355311DB030EA /* Pods-Runner.debug.xcconfig */,
22428D486F110EE0B969469D /* Pods-Runner.release.xcconfig */,
D3AD250AADBF93406007C9EB /* Pods-Runner.profile.xcconfig */,
2C0D722D2ED971BF672D18D5 /* Pods-RunnerTests.debug.xcconfig */,
877FDC97D8B87080E35B3EB7 /* Pods-RunnerTests.release.xcconfig */,
544621C7727C798253BAB2C8 /* Pods-RunnerTests.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
20A3C64D2B1CFED5A81C3251 /* Frameworks */ = {
isa = PBXGroup;
children = (
2AFAE479A87ECDEBD5D6EB30 /* Pods_Runner.framework */,
7ABF0EC746A2D686A0ED574F /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
331C8082294A63A400263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
331C807B294A618700263BE5 /* RunnerTests.swift */,
);
path = RunnerTests;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
331C8082294A63A400263BE5 /* RunnerTests */,
1454C118FFCECEEDF59152D2 /* Pods */,
20A3C64D2B1CFED5A81C3251 /* Frameworks */,
B14AB50E8716720E10D074BD /* GoogleService-Info.plist */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
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 = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
331C8080294A63A400263BE5 /* RunnerTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
B9A66CAAF434B6A1BD8C4E09 /* [CP] Check Pods Manifest.lock */,
331C807D294A63A400263BE5 /* Sources */,
331C807F294A63A400263BE5 /* Resources */,
759A57780A409ED209817654 /* Frameworks */,
);
buildRules = (
);
dependencies = (
331C8086294A63A400263BE5 /* PBXTargetDependency */,
);
name = RunnerTests;
productName = RunnerTests;
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
C1C48B0232C0B26BFF405512 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
33590C9CD073D3D5EBA02CDE /* [CP] Embed Pods Frameworks */,
7A77858F6F15CB76D2D3A872 /* FlutterFire: "flutterfire upload-crashlytics-symbols" */,
);
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 = {
BuildIndependentTargetsInParallel = YES;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C8080294A63A400263BE5 = {
CreatedOnToolsVersion = 14.0;
TestTargetID = 97C146ED1CF9000F007C117D;
};
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 */,
331C8080294A63A400263BE5 /* RunnerTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
331C807F294A63A400263BE5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
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 */,
F2A3345EC3021060731668D3 /* GoogleService-Info.plist in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
33590C9CD073D3D5EBA02CDE /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
7A77858F6F15CB76D2D3A872 /* FlutterFire: "flutterfire upload-crashlytics-symbols" */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "FlutterFire: \"flutterfire upload-crashlytics-symbols\"";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\n#!/bin/bash\nPATH=\"${PATH}:$FLUTTER_ROOT/bin:$HOME/.pub-cache/bin\"\nflutterfire upload-crashlytics-symbols --upload-symbols-script-path=\"$PODS_ROOT/FirebaseCrashlytics/upload-symbols\" --platform=ios --apple-project-path=\"${SRCROOT}\" --env-platform-name=\"${PLATFORM_NAME}\" --env-configuration=\"${CONFIGURATION}\" --env-project-dir=\"${PROJECT_DIR}\" --env-built-products-dir=\"${BUILT_PRODUCTS_DIR}\" --env-dwarf-dsym-folder-path=\"${DWARF_DSYM_FOLDER_PATH}\" --env-dwarf-dsym-file-name=\"${DWARF_DSYM_FILE_NAME}\" --env-infoplist-path=\"${INFOPLIST_PATH}\" --default-config=default\n";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
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";
};
B9A66CAAF434B6A1BD8C4E09 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
C1C48B0232C0B26BFF405512 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
331C807D294A63A400263BE5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 97C146ED1CF9000F007C117D /* Runner */;
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
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;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
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 = 12.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.syncrowWeb;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
331C8088294A63A400263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 2C0D722D2ED971BF672D18D5 /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.syncrowWeb.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Debug;
};
331C8089294A63A400263BE5 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 877FDC97D8B87080E35B3EB7 /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.syncrowWeb.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Release;
};
331C808A294A63A400263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 544621C7727C798253BAB2C8 /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.syncrowWeb.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
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;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
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 = 12.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;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
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;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
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 = 12.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.syncrowWeb;
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.syncrowWeb;
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 */
331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
331C8088294A63A400263BE5 /* Debug */,
331C8089294A63A400263BE5 /* Release */,
331C808A294A63A400263BE5 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
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 */;
}

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@ -1,98 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "331C8080294A63A400263BE5"
BuildableName = "RunnerTests.xctest"
BlueprintName = "RunnerTests"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@ -1,13 +0,0 @@
import UIKit
import Flutter
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}

View File

@ -1,122 +0,0 @@
{
"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"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,23 +0,0 @@
{
"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"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

View File

@ -1,5 +0,0 @@
# 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.

View File

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

View File

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>API_KEY</key>
<string>AIzaSyABnpH6yo2RRjtkp4PlvtK84hKwRm2DhBw</string>
<key>GCM_SENDER_ID</key>
<string>427332280600</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>com.example.syncrowWeb</string>
<key>PROJECT_ID</key>
<string>test2-8a3d2</string>
<key>STORAGE_BUCKET</key>
<string>test2-8a3d2.firebasestorage.app</string>
<key>IS_ADS_ENABLED</key>
<false></false>
<key>IS_ANALYTICS_ENABLED</key>
<false></false>
<key>IS_APPINVITE_ENABLED</key>
<true></true>
<key>IS_GCM_ENABLED</key>
<true></true>
<key>IS_SIGNIN_ENABLED</key>
<true></true>
<key>GOOGLE_APP_ID</key>
<string>1:427332280600:ios:14346b200780dc760c7e6d</string>
<key>DATABASE_URL</key>
<string>https://test2-8a3d2-default-rtdb.firebaseio.com</string>
</dict>
</plist>

View File

@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Syncrow Web</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>syncrow_web</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>

View File

@ -1 +0,0 @@
#import "GeneratedPluginRegistrant.h"

View File

@ -1,12 +0,0 @@
import Flutter
import UIKit
import XCTest
class RunnerTests: XCTestCase {
func testExample() {
// If you add code to the Runner application, consider adding tests here.
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
}
}

View File

@ -17,7 +17,8 @@ class TagDialogTextfieldDropdown extends StatefulWidget {
}) : super(key: key); }) : super(key: key);
@override @override
_DialogTextfieldDropdownState createState() => _DialogTextfieldDropdownState(); _DialogTextfieldDropdownState createState() =>
_DialogTextfieldDropdownState();
} }
class _DialogTextfieldDropdownState extends State<TagDialogTextfieldDropdown> { class _DialogTextfieldDropdownState extends State<TagDialogTextfieldDropdown> {
@ -36,6 +37,12 @@ class _DialogTextfieldDropdownState extends State<TagDialogTextfieldDropdown> {
_focusNode.addListener(() { _focusNode.addListener(() {
if (!_focusNode.hasFocus) { if (!_focusNode.hasFocus) {
// Call onSelected when focus is lost
final selectedTag = _filteredItems.firstWhere(
(tag) => tag.tag == _controller.text,
orElse: () => Tag(tag: _controller.text),
);
widget.onSelected(selectedTag);
_closeDropdown(); _closeDropdown();
} }
}); });
@ -43,7 +50,9 @@ class _DialogTextfieldDropdownState extends State<TagDialogTextfieldDropdown> {
void _filterItems() { void _filterItems() {
setState(() { setState(() {
_filteredItems = widget.items.where((tag) => tag.product?.uuid == widget.product).toList(); _filteredItems = widget.items;
// .where((tag) => tag.product?.uuid == widget.product)
// .toList();
}); });
} }
@ -112,7 +121,9 @@ class _DialogTextfieldDropdownState extends State<TagDialogTextfieldDropdown> {
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.bodyMedium .bodyMedium
?.copyWith(color: ColorsManager.textPrimaryColor)), ?.copyWith(
color: ColorsManager
.textPrimaryColor)),
onTap: () { onTap: () {
_controller.text = tag.tag ?? ''; _controller.text = tag.tag ?? '';
widget.onSelected(tag); widget.onSelected(tag);
@ -156,13 +167,15 @@ class _DialogTextfieldDropdownState extends State<TagDialogTextfieldDropdown> {
controller: _controller, controller: _controller,
focusNode: _focusNode, focusNode: _focusNode,
onFieldSubmitted: (value) { onFieldSubmitted: (value) {
final selectedTag = _filteredItems.firstWhere((tag) => tag.tag == value, final selectedTag = _filteredItems.firstWhere(
(tag) => tag.tag == value,
orElse: () => Tag(tag: value)); orElse: () => Tag(tag: value));
widget.onSelected(selectedTag); widget.onSelected(selectedTag);
_closeDropdown(); _closeDropdown();
}, },
onTapOutside: (event) { onTapOutside: (event) {
widget.onSelected(_filteredItems.firstWhere((tag) => tag.tag == _controller.text, widget.onSelected(_filteredItems.firstWhere(
(tag) => tag.tag == _controller.text,
orElse: () => Tag(tag: _controller.text))); orElse: () => Tag(tag: _controller.text)));
_closeDropdown(); _closeDropdown();
}, },

View File

@ -267,7 +267,8 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
selectedIndex = 0; selectedIndex = 0;
effectiveTimeTimeStamp = null; effectiveTimeTimeStamp = null;
expirationTimeTimeStamp = null; expirationTimeTimeStamp = null;
add(FetchTableData()); filteredData = List.from(data);
emit(TableLoaded(filteredData));
} }
String timestampToDate(dynamic timestamp) { String timestampToDate(dynamic timestamp) {

View File

@ -3,6 +3,7 @@ import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/analytics/models/analytics_device.dart'; import 'package:syncrow_web/pages/analytics/models/analytics_device.dart';
import 'package:syncrow_web/pages/analytics/params/get_analytics_devices_param.dart'; import 'package:syncrow_web/pages/analytics/params/get_analytics_devices_param.dart';
import 'package:syncrow_web/pages/analytics/services/analytics_devices/analytics_devices_service.dart'; import 'package:syncrow_web/pages/analytics/services/analytics_devices/analytics_devices_service.dart';
import 'package:syncrow_web/services/api/api_exception.dart';
part 'analytics_devices_event.dart'; part 'analytics_devices_event.dart';
part 'analytics_devices_state.dart'; part 'analytics_devices_state.dart';
@ -36,6 +37,13 @@ class AnalyticsDevicesBloc
if (devices.isNotEmpty) { if (devices.isNotEmpty) {
event.onSuccess(devices.first); event.onSuccess(devices.first);
} }
} on APIException catch (e) {
emit(
AnalyticsDevicesState(
status: AnalyticsDevicesStatus.failure,
errorMessage: e.message,
),
);
} catch (e) { } catch (e) {
emit( emit(
AnalyticsDevicesState( AnalyticsDevicesState(

View File

@ -3,6 +3,7 @@ import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/analytics/models/phases_energy_consumption.dart'; import 'package:syncrow_web/pages/analytics/models/phases_energy_consumption.dart';
import 'package:syncrow_web/pages/analytics/params/get_energy_consumption_by_phases_param.dart'; import 'package:syncrow_web/pages/analytics/params/get_energy_consumption_by_phases_param.dart';
import 'package:syncrow_web/pages/analytics/services/energy_consumption_by_phases/energy_consumption_by_phases_service.dart'; import 'package:syncrow_web/pages/analytics/services/energy_consumption_by_phases/energy_consumption_by_phases_service.dart';
import 'package:syncrow_web/services/api/api_exception.dart';
part 'energy_consumption_by_phases_event.dart'; part 'energy_consumption_by_phases_event.dart';
part 'energy_consumption_by_phases_state.dart'; part 'energy_consumption_by_phases_state.dart';
@ -31,6 +32,13 @@ class EnergyConsumptionByPhasesBloc
chartData: chartData, chartData: chartData,
), ),
); );
} on APIException catch (e) {
emit(
state.copyWith(
status: EnergyConsumptionByPhasesStatus.failure,
errorMessage: e.message,
),
);
} catch (e) { } catch (e) {
emit( emit(
state.copyWith( state.copyWith(

View File

@ -3,6 +3,7 @@ import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/analytics/models/device_energy_data_model.dart'; import 'package:syncrow_web/pages/analytics/models/device_energy_data_model.dart';
import 'package:syncrow_web/pages/analytics/params/get_energy_consumption_per_device_param.dart'; import 'package:syncrow_web/pages/analytics/params/get_energy_consumption_per_device_param.dart';
import 'package:syncrow_web/pages/analytics/services/energy_consumption_per_device/energy_consumption_per_device_service.dart'; import 'package:syncrow_web/pages/analytics/services/energy_consumption_per_device/energy_consumption_per_device_service.dart';
import 'package:syncrow_web/services/api/api_exception.dart';
part 'energy_consumption_per_device_event.dart'; part 'energy_consumption_per_device_event.dart';
part 'energy_consumption_per_device_state.dart'; part 'energy_consumption_per_device_state.dart';
@ -13,7 +14,8 @@ class EnergyConsumptionPerDeviceBloc
this._energyConsumptionPerDeviceService, this._energyConsumptionPerDeviceService,
) : super(const EnergyConsumptionPerDeviceState()) { ) : super(const EnergyConsumptionPerDeviceState()) {
on<LoadEnergyConsumptionPerDeviceEvent>(_onLoadEnergyConsumptionPerDeviceEvent); on<LoadEnergyConsumptionPerDeviceEvent>(_onLoadEnergyConsumptionPerDeviceEvent);
on<ClearEnergyConsumptionPerDeviceEvent>(_onClearEnergyConsumptionPerDeviceEvent); on<ClearEnergyConsumptionPerDeviceEvent>(
_onClearEnergyConsumptionPerDeviceEvent);
} }
final EnergyConsumptionPerDeviceService _energyConsumptionPerDeviceService; final EnergyConsumptionPerDeviceService _energyConsumptionPerDeviceService;
@ -31,6 +33,13 @@ class EnergyConsumptionPerDeviceBloc
chartData: chartData, chartData: chartData,
), ),
); );
} on APIException catch (e) {
emit(
state.copyWith(
status: EnergyConsumptionPerDeviceStatus.failure,
errorMessage: e.message,
),
);
} catch (e) { } catch (e) {
emit( emit(
state.copyWith( state.copyWith(

View File

@ -3,6 +3,7 @@ import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/analytics/services/power_clamp_info/power_clamp_info_service.dart'; import 'package:syncrow_web/pages/analytics/services/power_clamp_info/power_clamp_info_service.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
import 'package:syncrow_web/pages/device_managment/power_clamp/models/power_clamp_model.dart'; import 'package:syncrow_web/pages/device_managment/power_clamp/models/power_clamp_model.dart';
import 'package:syncrow_web/services/api/api_exception.dart';
part 'power_clamp_info_event.dart'; part 'power_clamp_info_event.dart';
part 'power_clamp_info_state.dart'; part 'power_clamp_info_state.dart';
@ -31,6 +32,13 @@ class PowerClampInfoBloc extends Bloc<PowerClampInfoEvent, PowerClampInfoState>
powerClampModel: powerClampModel, powerClampModel: powerClampModel,
), ),
); );
} on APIException catch (e) {
emit(
state.copyWith(
status: PowerClampInfoStatus.error,
errorMessage: e.message,
),
);
} catch (e) { } catch (e) {
emit( emit(
state.copyWith( state.copyWith(

View File

@ -3,6 +3,7 @@ import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/analytics/models/energy_data_model.dart'; import 'package:syncrow_web/pages/analytics/models/energy_data_model.dart';
import 'package:syncrow_web/pages/analytics/params/get_total_energy_consumption_param.dart'; import 'package:syncrow_web/pages/analytics/params/get_total_energy_consumption_param.dart';
import 'package:syncrow_web/pages/analytics/services/total_energy_consumption/total_energy_consumption_service.dart'; import 'package:syncrow_web/pages/analytics/services/total_energy_consumption/total_energy_consumption_service.dart';
import 'package:syncrow_web/services/api/api_exception.dart';
part 'total_energy_consumption_event.dart'; part 'total_energy_consumption_event.dart';
part 'total_energy_consumption_state.dart'; part 'total_energy_consumption_state.dart';
@ -31,6 +32,13 @@ class TotalEnergyConsumptionBloc
status: TotalEnergyConsumptionStatus.loaded, status: TotalEnergyConsumptionStatus.loaded,
), ),
); );
} on APIException catch (e) {
emit(
state.copyWith(
errorMessage: e.message,
status: TotalEnergyConsumptionStatus.failure,
),
);
} catch (e) { } catch (e) {
emit( emit(
state.copyWith( state.copyWith(

View File

@ -1,34 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/helpers/fetch_energy_management_data_helper.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/energy_consumption_per_device_chart_box.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/energy_consumption_per_device_chart_box.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/power_clamp_energy_data_widget.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/power_clamp_energy_data_widget.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/total_energy_consumption_chart_box.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/total_energy_consumption_chart_box.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
class AnalyticsEnergyManagementView extends StatefulWidget { class AnalyticsEnergyManagementView extends StatelessWidget {
const AnalyticsEnergyManagementView({super.key}); const AnalyticsEnergyManagementView({super.key});
@override
State<AnalyticsEnergyManagementView> createState() =>
_AnalyticsEnergyManagementViewState();
}
class _AnalyticsEnergyManagementViewState
extends State<AnalyticsEnergyManagementView> {
@override
void initState() {
final spaceTreeBloc = context.read<SpaceTreeBloc>();
final communityId = spaceTreeBloc.state.selectedCommunities.firstOrNull;
final spaceId = spaceTreeBloc.state.selectedSpaces.firstOrNull;
FetchEnergyManagementDataHelper.loadEnergyManagementData(
context,
communityId: communityId ?? '',
spaceId: spaceId ?? '',
);
super.initState();
}
static const _padding = EdgeInsetsDirectional.all(32); static const _padding = EdgeInsetsDirectional.all(32);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -3,6 +3,7 @@ import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/analytics/models/occupacy.dart'; import 'package:syncrow_web/pages/analytics/models/occupacy.dart';
import 'package:syncrow_web/pages/analytics/params/get_occupancy_param.dart'; import 'package:syncrow_web/pages/analytics/params/get_occupancy_param.dart';
import 'package:syncrow_web/pages/analytics/services/occupacy/occupacy_service.dart'; import 'package:syncrow_web/pages/analytics/services/occupacy/occupacy_service.dart';
import 'package:syncrow_web/services/api/api_exception.dart';
part 'occupancy_event.dart'; part 'occupancy_event.dart';
part 'occupancy_state.dart'; part 'occupancy_state.dart';
@ -23,6 +24,8 @@ class OccupancyBloc extends Bloc<OccupancyEvent, OccupancyState> {
try { try {
final chartData = await _occupacyService.load(event.param); final chartData = await _occupacyService.load(event.param);
emit(state.copyWith(chartData: chartData, status: OccupancyStatus.loaded)); emit(state.copyWith(chartData: chartData, status: OccupancyStatus.loaded));
} on APIException catch (e) {
emit(state.copyWith(status: OccupancyStatus.failure, errorMessage: e.message));
} catch (e) { } catch (e) {
emit(state.copyWith(status: OccupancyStatus.failure, errorMessage: '$e')); emit(state.copyWith(status: OccupancyStatus.failure, errorMessage: '$e'));
} }

View File

@ -3,6 +3,7 @@ import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/analytics/models/occupancy_heat_map_model.dart'; import 'package:syncrow_web/pages/analytics/models/occupancy_heat_map_model.dart';
import 'package:syncrow_web/pages/analytics/params/get_occupancy_heat_map_param.dart'; import 'package:syncrow_web/pages/analytics/params/get_occupancy_heat_map_param.dart';
import 'package:syncrow_web/pages/analytics/services/occupancy_heat_map/occupancy_heat_map_service.dart'; import 'package:syncrow_web/pages/analytics/services/occupancy_heat_map/occupancy_heat_map_service.dart';
import 'package:syncrow_web/services/api/api_exception.dart';
part 'occupancy_heat_map_event.dart'; part 'occupancy_heat_map_event.dart';
part 'occupancy_heat_map_state.dart'; part 'occupancy_heat_map_state.dart';
@ -30,6 +31,13 @@ class OccupancyHeatMapBloc
heatMapData: occupancyHeatMap, heatMapData: occupancyHeatMap,
), ),
); );
} on APIException catch (e) {
emit(
state.copyWith(
status: OccupancyHeatMapStatus.failure,
errorMessage: e.message,
),
);
} catch (e) { } catch (e) {
emit( emit(
state.copyWith( state.copyWith(

View File

@ -10,7 +10,7 @@ class GetEnergyConsumptionPerDeviceParam {
Map<String, dynamic> toJson() => { Map<String, dynamic> toJson() => {
'monthDate': 'monthDate':
'${monthDate?.year}-${monthDate?.month.toString().padLeft(2, '0')}', '${monthDate?.year}-${monthDate?.month.toString().padLeft(2, '0')}',
if (spaceId == null || spaceId == null) 'spaceUuid': spaceId, if (spaceId != null) 'spaceUuid': spaceId,
'groupByDevice': true, 'groupByDevice': true,
}; };
} }

View File

@ -11,7 +11,7 @@ class GetTotalEnergyConsumptionParam {
return { return {
'monthDate': 'monthDate':
'${monthDate?.year}-${monthDate?.month.toString().padLeft(2, '0')}', '${monthDate?.year}-${monthDate?.month.toString().padLeft(2, '0')}',
if (spaceId == null || spaceId == null) 'spaceUuid': spaceId, if (spaceId != null) 'spaceUuid': spaceId,
'groupByDevice': false, 'groupByDevice': false,
}; };
} }

View File

@ -1,6 +1,8 @@
import 'package:dio/dio.dart';
import 'package:syncrow_web/pages/analytics/models/analytics_device.dart'; import 'package:syncrow_web/pages/analytics/models/analytics_device.dart';
import 'package:syncrow_web/pages/analytics/params/get_analytics_devices_param.dart'; import 'package:syncrow_web/pages/analytics/params/get_analytics_devices_param.dart';
import 'package:syncrow_web/pages/analytics/services/analytics_devices/analytics_devices_service.dart'; import 'package:syncrow_web/pages/analytics/services/analytics_devices/analytics_devices_service.dart';
import 'package:syncrow_web/services/api/api_exception.dart';
import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/services/api/http_service.dart';
final class RemoteEnergyManagementAnalyticsDevicesService final class RemoteEnergyManagementAnalyticsDevicesService
@ -9,6 +11,8 @@ final class RemoteEnergyManagementAnalyticsDevicesService
final HTTPService _httpService; final HTTPService _httpService;
static const _defaultErrorMessage = 'Failed to load analytics devices';
@override @override
Future<List<AnalyticsDevice>> getDevices(GetAnalyticsDevicesParam param) async { Future<List<AnalyticsDevice>> getDevices(GetAnalyticsDevicesParam param) async {
try { try {
@ -29,8 +33,14 @@ final class RemoteEnergyManagementAnalyticsDevicesService
); );
return response; return response;
} on DioException catch (e) {
final message = e.response?.data as Map<String, dynamic>?;
final error = message?['error'] as Map<String, dynamic>?;
final errorMessage = error?['error'] as String? ?? '';
final formattedErrorMessage = [_defaultErrorMessage, errorMessage].join(': ');
throw APIException(formattedErrorMessage);
} catch (e) { } catch (e) {
throw Exception('Failed to load total energy consumption: $e'); throw APIException('$_defaultErrorMessage: $e');
} }
} }
} }

View File

@ -1,7 +1,9 @@
import 'package:dio/dio.dart';
import 'package:syncrow_web/pages/analytics/models/analytics_device.dart'; import 'package:syncrow_web/pages/analytics/models/analytics_device.dart';
import 'package:syncrow_web/pages/analytics/params/get_analytics_devices_param.dart'; import 'package:syncrow_web/pages/analytics/params/get_analytics_devices_param.dart';
import 'package:syncrow_web/pages/analytics/services/analytics_devices/analytics_devices_service.dart'; import 'package:syncrow_web/pages/analytics/services/analytics_devices/analytics_devices_service.dart';
import 'package:syncrow_web/pages/common/bloc/project_manager.dart'; import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
import 'package:syncrow_web/services/api/api_exception.dart';
import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/services/api/http_service.dart';
class RemoteOccupancyAnalyticsDevicesService implements AnalyticsDevicesService { class RemoteOccupancyAnalyticsDevicesService implements AnalyticsDevicesService {
@ -9,6 +11,8 @@ class RemoteOccupancyAnalyticsDevicesService implements AnalyticsDevicesService
final HTTPService _httpService; final HTTPService _httpService;
static const _defaultErrorMessage = 'Failed to load analytics devices';
@override @override
Future<List<AnalyticsDevice>> getDevices(GetAnalyticsDevicesParam param) async { Future<List<AnalyticsDevice>> getDevices(GetAnalyticsDevicesParam param) async {
try { try {
@ -26,8 +30,15 @@ class RemoteOccupancyAnalyticsDevicesService implements AnalyticsDevicesService
final result = requests.map((e) => e.first).toList(); final result = requests.map((e) => e.first).toList();
return result; return result;
} on DioException catch (e) {
final message = e.response?.data as Map<String, dynamic>?;
final error = message?['error'] as Map<String, dynamic>?;
final errorMessage = error?['error'] as String? ?? '';
final formattedErrorMessage = [_defaultErrorMessage, errorMessage].join(': ');
throw APIException(formattedErrorMessage);
} catch (e) { } catch (e) {
throw Exception('Failed to load total energy consumption: $e'); final formattedErrorMessage = [_defaultErrorMessage, e.toString()].join(': ');
throw APIException(formattedErrorMessage);
} }
} }
@ -54,8 +65,14 @@ class RemoteOccupancyAnalyticsDevicesService implements AnalyticsDevicesService
}, },
); );
return response; return response;
} on DioException catch (e) {
final message = e.response?.data as Map<String, dynamic>?;
final error = message?['error'] as Map<String, dynamic>?;
final errorMessage = error?['error'] as String? ?? '';
final formattedErrorMessage = [_defaultErrorMessage, errorMessage].join(': ');
throw APIException(formattedErrorMessage);
} catch (e) { } catch (e) {
rethrow; throw APIException('$_defaultErrorMessage: $e');
} }
} }
} }

View File

@ -1,6 +1,8 @@
import 'package:dio/dio.dart';
import 'package:syncrow_web/pages/analytics/models/phases_energy_consumption.dart'; import 'package:syncrow_web/pages/analytics/models/phases_energy_consumption.dart';
import 'package:syncrow_web/pages/analytics/params/get_energy_consumption_by_phases_param.dart'; import 'package:syncrow_web/pages/analytics/params/get_energy_consumption_by_phases_param.dart';
import 'package:syncrow_web/pages/analytics/services/energy_consumption_by_phases/energy_consumption_by_phases_service.dart'; import 'package:syncrow_web/pages/analytics/services/energy_consumption_by_phases/energy_consumption_by_phases_service.dart';
import 'package:syncrow_web/services/api/api_exception.dart';
import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/services/api/http_service.dart';
final class RemoteEnergyConsumptionByPhasesService final class RemoteEnergyConsumptionByPhasesService
@ -9,6 +11,8 @@ final class RemoteEnergyConsumptionByPhasesService
final HTTPService _httpService; final HTTPService _httpService;
static const _defaultErrorMessage = 'Failed to load energy consumption per phase';
@override @override
Future<List<PhasesEnergyConsumption>> load( Future<List<PhasesEnergyConsumption>> load(
GetEnergyConsumptionByPhasesParam param, GetEnergyConsumptionByPhasesParam param,
@ -28,8 +32,15 @@ final class RemoteEnergyConsumptionByPhasesService
}, },
); );
return response; return response;
} on DioException catch (e) {
final message = e.response?.data as Map<String, dynamic>?;
final error = message?['error'] as Map<String, dynamic>?;
final errorMessage = error?['error'] as String? ?? '';
final formattedErrorMessage = [_defaultErrorMessage, errorMessage].join(': ');
throw APIException(formattedErrorMessage);
} catch (e) { } catch (e) {
throw Exception('Failed to load energy consumption per phase: $e'); final formattedErrorMessage = [_defaultErrorMessage, '$e'].join(': ');
throw APIException(formattedErrorMessage);
} }
} }
} }

View File

@ -1,8 +1,10 @@
import 'package:dio/dio.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/analytics/models/device_energy_data_model.dart'; import 'package:syncrow_web/pages/analytics/models/device_energy_data_model.dart';
import 'package:syncrow_web/pages/analytics/models/energy_data_model.dart'; import 'package:syncrow_web/pages/analytics/models/energy_data_model.dart';
import 'package:syncrow_web/pages/analytics/params/get_energy_consumption_per_device_param.dart'; import 'package:syncrow_web/pages/analytics/params/get_energy_consumption_per_device_param.dart';
import 'package:syncrow_web/pages/analytics/services/energy_consumption_per_device/energy_consumption_per_device_service.dart'; import 'package:syncrow_web/pages/analytics/services/energy_consumption_per_device/energy_consumption_per_device_service.dart';
import 'package:syncrow_web/services/api/api_exception.dart';
import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/services/api/http_service.dart';
class RemoteEnergyConsumptionPerDeviceService class RemoteEnergyConsumptionPerDeviceService
@ -11,6 +13,8 @@ class RemoteEnergyConsumptionPerDeviceService
final HTTPService _httpService; final HTTPService _httpService;
static const _defaultErrorMessage = 'Failed to load energy consumption per device';
@override @override
Future<List<DeviceEnergyDataModel>> load( Future<List<DeviceEnergyDataModel>> load(
GetEnergyConsumptionPerDeviceParam param, GetEnergyConsumptionPerDeviceParam param,
@ -23,8 +27,15 @@ class RemoteEnergyConsumptionPerDeviceService
expectedResponseModel: _EnergyConsumptionPerDeviceMapper.map, expectedResponseModel: _EnergyConsumptionPerDeviceMapper.map,
); );
return response; return response;
} on DioException catch (e) {
final message = e.response?.data as Map<String, dynamic>?;
final error = message?['error'] as Map<String, dynamic>?;
final errorMessage = error?['error'] as String? ?? '';
final formattedErrorMessage = [_defaultErrorMessage, errorMessage].join(': ');
throw APIException(formattedErrorMessage);
} catch (e) { } catch (e) {
throw Exception('Failed to load energy consumption per device: $e'); final formattedErrorMessage = [_defaultErrorMessage, '$e'].join(': ');
throw APIException(formattedErrorMessage);
} }
} }
} }

View File

@ -1,6 +1,8 @@
import 'package:dio/dio.dart';
import 'package:syncrow_web/pages/analytics/models/occupacy.dart'; import 'package:syncrow_web/pages/analytics/models/occupacy.dart';
import 'package:syncrow_web/pages/analytics/params/get_occupancy_param.dart'; import 'package:syncrow_web/pages/analytics/params/get_occupancy_param.dart';
import 'package:syncrow_web/pages/analytics/services/occupacy/occupacy_service.dart'; import 'package:syncrow_web/pages/analytics/services/occupacy/occupacy_service.dart';
import 'package:syncrow_web/services/api/api_exception.dart';
import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/services/api/http_service.dart';
final class RemoteOccupancyService implements OccupacyService { final class RemoteOccupancyService implements OccupacyService {
@ -8,6 +10,8 @@ final class RemoteOccupancyService implements OccupacyService {
final HTTPService _httpService; final HTTPService _httpService;
static const _defaultErrorMessage = 'Failed to load occupancy';
@override @override
Future<List<Occupacy>> load(GetOccupancyParam param) async { Future<List<Occupacy>> load(GetOccupancyParam param) async {
try { try {
@ -25,8 +29,15 @@ final class RemoteOccupancyService implements OccupacyService {
}, },
); );
return response; return response;
} on DioException catch (e) {
final message = e.response?.data as Map<String, dynamic>?;
final error = message?['error'] as Map<String, dynamic>?;
final errorMessage = error?['error'] as String? ?? '';
final formattedErrorMessage = [_defaultErrorMessage, errorMessage].join(': ');
throw APIException(formattedErrorMessage);
} catch (e) { } catch (e) {
throw Exception('Failed to load energy consumption per phase: $e'); final formattedErrorMessage = [_defaultErrorMessage, '$e'].join(': ');
throw APIException(formattedErrorMessage);
} }
} }
} }

View File

@ -1,6 +1,8 @@
import 'package:dio/dio.dart';
import 'package:syncrow_web/pages/analytics/models/occupancy_heat_map_model.dart'; import 'package:syncrow_web/pages/analytics/models/occupancy_heat_map_model.dart';
import 'package:syncrow_web/pages/analytics/params/get_occupancy_heat_map_param.dart'; import 'package:syncrow_web/pages/analytics/params/get_occupancy_heat_map_param.dart';
import 'package:syncrow_web/pages/analytics/services/occupancy_heat_map/occupancy_heat_map_service.dart'; import 'package:syncrow_web/pages/analytics/services/occupancy_heat_map/occupancy_heat_map_service.dart';
import 'package:syncrow_web/services/api/api_exception.dart';
import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/services/api/http_service.dart';
final class RemoteOccupancyHeatMapService implements OccupancyHeatMapService { final class RemoteOccupancyHeatMapService implements OccupancyHeatMapService {
@ -8,6 +10,8 @@ final class RemoteOccupancyHeatMapService implements OccupancyHeatMapService {
final HTTPService _httpService; final HTTPService _httpService;
static const _defaultErrorMessage = 'Failed to load occupancy heat map';
@override @override
Future<List<OccupancyHeatMapModel>> load(GetOccupancyHeatMapParam param) async { Future<List<OccupancyHeatMapModel>> load(GetOccupancyHeatMapParam param) async {
try { try {
@ -28,8 +32,15 @@ final class RemoteOccupancyHeatMapService implements OccupancyHeatMapService {
); );
return response; return response;
} on DioException catch (e) {
final message = e.response?.data as Map<String, dynamic>?;
final error = message?['error'] as Map<String, dynamic>?;
final errorMessage = error?['error'] as String? ?? '';
final formattedErrorMessage = [_defaultErrorMessage, errorMessage].join(': ');
throw APIException(formattedErrorMessage);
} catch (e) { } catch (e) {
throw Exception('Failed to load total energy consumption:'); final formattedErrorMessage = [_defaultErrorMessage, '$e'].join(': ');
throw APIException(formattedErrorMessage);
} }
} }
} }

View File

@ -1,5 +1,7 @@
import 'package:dio/dio.dart';
import 'package:syncrow_web/pages/analytics/services/power_clamp_info/power_clamp_info_service.dart'; import 'package:syncrow_web/pages/analytics/services/power_clamp_info/power_clamp_info_service.dart';
import 'package:syncrow_web/pages/device_managment/power_clamp/models/power_clamp_model.dart'; import 'package:syncrow_web/pages/device_managment/power_clamp/models/power_clamp_model.dart';
import 'package:syncrow_web/services/api/api_exception.dart';
import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/services/api/http_service.dart';
final class RemotePowerClampInfoService implements PowerClampInfoService { final class RemotePowerClampInfoService implements PowerClampInfoService {
@ -7,6 +9,8 @@ final class RemotePowerClampInfoService implements PowerClampInfoService {
final HTTPService _httpService; final HTTPService _httpService;
static const _defaultErrorMessage = 'Failed to fetch power clamp info';
@override @override
Future<PowerClampModel> getInfo(String deviceId) async { Future<PowerClampModel> getInfo(String deviceId) async {
try { try {
@ -20,8 +24,15 @@ final class RemotePowerClampInfoService implements PowerClampInfoService {
}, },
); );
return response; return response;
} on DioException catch (e) {
final message = e.response?.data as Map<String, dynamic>?;
final error = message?['error'] as Map<String, dynamic>?;
final errorMessage = error?['error'] as String? ?? '';
final formattedErrorMessage = [_defaultErrorMessage, errorMessage].join(': ');
throw APIException(formattedErrorMessage);
} catch (e) { } catch (e) {
throw Exception('Failed to fetch power clamp info: $e'); final formattedErrorMessage = [_defaultErrorMessage, '$e'].join(': ');
throw APIException(formattedErrorMessage);
} }
} }
} }

View File

@ -1,6 +1,8 @@
import 'package:dio/dio.dart';
import 'package:syncrow_web/pages/analytics/models/energy_data_model.dart'; import 'package:syncrow_web/pages/analytics/models/energy_data_model.dart';
import 'package:syncrow_web/pages/analytics/params/get_total_energy_consumption_param.dart'; import 'package:syncrow_web/pages/analytics/params/get_total_energy_consumption_param.dart';
import 'package:syncrow_web/pages/analytics/services/total_energy_consumption/total_energy_consumption_service.dart'; import 'package:syncrow_web/pages/analytics/services/total_energy_consumption/total_energy_consumption_service.dart';
import 'package:syncrow_web/services/api/api_exception.dart';
import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/services/api/http_service.dart';
class RemoteTotalEnergyConsumptionService implements TotalEnergyConsumptionService { class RemoteTotalEnergyConsumptionService implements TotalEnergyConsumptionService {
@ -8,6 +10,8 @@ class RemoteTotalEnergyConsumptionService implements TotalEnergyConsumptionServi
final HTTPService _httpService; final HTTPService _httpService;
static const _defaultErrorMessage = 'Failed to load total energy consumption';
@override @override
Future<List<EnergyDataModel>> load( Future<List<EnergyDataModel>> load(
GetTotalEnergyConsumptionParam param, GetTotalEnergyConsumptionParam param,
@ -21,8 +25,15 @@ class RemoteTotalEnergyConsumptionService implements TotalEnergyConsumptionServi
); );
return response; return response;
} on DioException catch (e) {
final message = e.response?.data as Map<String, dynamic>?;
final error = message?['error'] as Map<String, dynamic>?;
final errorMessage = error?['error'] as String? ?? '';
final formattedErrorMessage = [_defaultErrorMessage, errorMessage].join(': ');
throw APIException(formattedErrorMessage);
} catch (e) { } catch (e) {
throw Exception('Failed to load total energy consumption: $e'); final formattedErrorMessage = [_defaultErrorMessage, '$e'].join(': ');
throw APIException(formattedErrorMessage);
} }
} }
} }

View File

@ -162,31 +162,34 @@ class _DynamicTableState extends State<DynamicTable> {
child: SingleChildScrollView( child: SingleChildScrollView(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
controller: _horizontalBodyScrollController, controller: _horizontalBodyScrollController,
child: SizedBox( child: Container(
width: widget.size.width, color: ColorsManager.whiteColors,
child: widget.isEmpty child: SizedBox(
? _buildEmptyState() width: widget.size.width,
: Column( child: widget.isEmpty
children: ? _buildEmptyState()
List.generate(widget.data.length, (rowIndex) { : Column(
final row = widget.data[rowIndex]; children: List.generate(widget.data.length,
return Row( (rowIndex) {
children: [ final row = widget.data[rowIndex];
if (widget.withCheckBox) return Row(
_buildRowCheckbox( children: [
rowIndex, widget.size.height * 0.08), if (widget.withCheckBox)
...row.asMap().entries.map((entry) { _buildRowCheckbox(rowIndex,
return _buildTableCell( widget.size.height * 0.08),
entry.value.toString(), ...row.asMap().entries.map((entry) {
widget.size.height * 0.08, return _buildTableCell(
rowIndex: rowIndex, entry.value.toString(),
columnIndex: entry.key, widget.size.height * 0.08,
); rowIndex: rowIndex,
}).toList(), columnIndex: entry.key,
], );
); }).toList(),
}), ],
), );
}),
),
),
), ),
), ),
), ),
@ -211,7 +214,6 @@ class _DynamicTableState extends State<DynamicTable> {
onChanged: widget.withSelectAll && widget.data.isNotEmpty onChanged: widget.withSelectAll && widget.data.isNotEmpty
? _toggleSelectAll ? _toggleSelectAll
: null, : null,
), ),
); );
} }
@ -282,7 +284,6 @@ class _DynamicTableState extends State<DynamicTable> {
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: index == widget.headers.length - 1 ? 12 : 8.0, horizontal: index == widget.headers.length - 1 ? 12 : 8.0,
vertical: 4), vertical: 4),
child: Text( child: Text(
title, title,
style: context.textTheme.titleSmall!.copyWith( style: context.textTheme.titleSmall!.copyWith(
@ -303,7 +304,6 @@ class _DynamicTableState extends State<DynamicTable> {
required int rowIndex, required int rowIndex,
required int columnIndex, required int columnIndex,
}) { }) {
bool isBatteryLevel = content.endsWith('%'); bool isBatteryLevel = content.endsWith('%');
double? batteryLevel; double? batteryLevel;
@ -313,9 +313,13 @@ class _DynamicTableState extends State<DynamicTable> {
bool isSettingsColumn = widget.headers[columnIndex] == 'Settings'; bool isSettingsColumn = widget.headers[columnIndex] == 'Settings';
if (isSettingsColumn) { if (isSettingsColumn) {
return _buildSettingsIcon(rowIndex, size); return buildSettingsIcon(
width: 120,
height: 60,
iconSize: 40,
onTap: () => widget.onSettingsPressed?.call(rowIndex),
);
} }
Color? statusColor; Color? statusColor;
switch (content) { switch (content) {
@ -368,22 +372,63 @@ class _DynamicTableState extends State<DynamicTable> {
); );
} }
Widget _buildSettingsIcon(int rowIndex, double size) { Widget buildSettingsIcon(
return Container( {double width = 120,
height: size, double height = 60,
width: 120, double iconSize = 40,
padding: const EdgeInsets.all(5.0), VoidCallback? onTap}) {
decoration: const BoxDecoration( return Column(
border: Border( children: [
bottom: BorderSide(color: ColorsManager.boxDivider, width: 1.0), Container(
padding: const EdgeInsets.only(top: 10, bottom: 15, left: 10),
margin: const EdgeInsets.only(right: 15),
decoration: const BoxDecoration(
color: ColorsManager.whiteColors,
border: Border(
bottom: BorderSide(
color: ColorsManager.boxDivider,
width: 1.0,
),
),
),
width: width,
child: Padding(
padding: const EdgeInsets.only(
right: 16.0,
left: 17.0,
),
child: Container(
width: 50,
decoration: BoxDecoration(
color: const Color(0xFFF7F8FA),
borderRadius: BorderRadius.circular(height / 2),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.17),
blurRadius: 14,
offset: const Offset(0, 4),
),
],
),
child: InkWell(
onTap: onTap,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: SvgPicture.asset(
Assets.settings, // ضع المسار الصحيح هنا
width: 40,
height: 22,
color: ColorsManager
.primaryColor, // نفس لون الأيقونة في الصورة
),
),
),
),
),
),
), ),
color: Colors.white, ],
),
alignment: Alignment.center,
child: IconButton(
icon: SvgPicture.asset(Assets.settings),
onPressed: () => widget.onSettingsPressed?.call(rowIndex),
),
); );
} }
} }

View File

@ -40,17 +40,18 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
style: TextButton.styleFrom( style: TextButton.styleFrom(
backgroundColor: null, backgroundColor: null,
), ),
onPressed: () { onPressed: !state.routineTab
BlocProvider.of<CreateRoutineBloc>(context) ? null
.add(const ResetSelectedEvent()); : () {
BlocProvider.of<CreateRoutineBloc>(context)
.add(const ResetSelectedEvent());
context context.read<RoutineBloc>().add(
.read<RoutineBloc>() const TriggerSwitchTabsEvent(isRoutineTab: false));
.add(const TriggerSwitchTabsEvent(isRoutineTab: false)); context
context .read<DeviceManagementBloc>()
.read<DeviceManagementBloc>() .add(FetchDevices(context));
.add(FetchDevices(context)); },
},
child: Text( child: Text(
'Devices', 'Devices',
style: context.textTheme.titleMedium?.copyWith( style: context.textTheme.titleMedium?.copyWith(
@ -66,14 +67,15 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
style: TextButton.styleFrom( style: TextButton.styleFrom(
backgroundColor: null, backgroundColor: null,
), ),
onPressed: () { onPressed: state.routineTab
BlocProvider.of<CreateRoutineBloc>(context) ? null
.add(const ResetSelectedEvent()); : () {
BlocProvider.of<CreateRoutineBloc>(context)
.add(const ResetSelectedEvent());
context context.read<RoutineBloc>().add(
.read<RoutineBloc>() const TriggerSwitchTabsEvent(isRoutineTab: true));
.add(const TriggerSwitchTabsEvent(isRoutineTab: true)); },
},
child: Text( child: Text(
'Routines', 'Routines',
style: context.textTheme.titleMedium?.copyWith( style: context.textTheme.titleMedium?.copyWith(

View File

@ -34,7 +34,8 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
runSpacing: 10, runSpacing: 10,
children: [ children: [
_buildSearchField("Space Name", _unitNameController, 200), _buildSearchField("Space Name", _unitNameController, 200),
_buildSearchField("Device Name / Product Name", _productNameController, 300), _buildSearchField(
"Device Name / Product Name", _productNameController, 300),
_buildSearchResetButtons(), _buildSearchResetButtons(),
], ],
); );
@ -74,9 +75,7 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
onReset: () { onReset: () {
_unitNameController.clear(); _unitNameController.clear();
_productNameController.clear(); _productNameController.clear();
context.read<DeviceManagementBloc>() context.read<DeviceManagementBloc>().add(ResetFilters());
..add(ResetFilters())
..add(FetchDevices(context));
}, },
); );
} }

View File

@ -1,10 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/device_managment/device_setting/settings_model/device_info_model.dart'; import 'package:syncrow_web/pages/device_managment/device_setting/settings_model/device_info_model.dart';
import 'package:syncrow_web/pages/device_managment/device_setting/settings_model/sub_space_model.dart'; import 'package:syncrow_web/pages/device_managment/device_setting/settings_model/sub_space_model.dart';
import 'package:syncrow_web/pages/device_managment/device_setting/sub_space_dialog.dart'; import 'package:syncrow_web/pages/device_managment/device_setting/sub_space_dialog.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';
import 'package:syncrow_web/web_layout/default_container.dart'; import 'package:syncrow_web/web_layout/default_container.dart';
@ -28,7 +30,7 @@ class DeviceManagementContent extends StatelessWidget {
Widget? trailing, Widget? trailing,
required Color? valueColor}) { required Color? valueColor}) {
return Padding( return Padding(
padding: const EdgeInsets.symmetric(vertical: 6.0), padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 10),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
@ -39,6 +41,7 @@ class DeviceManagementContent extends StatelessWidget {
color: ColorsManager.grayColor, color: ColorsManager.grayColor,
), ),
), ),
const SizedBox(width: 15),
Expanded( Expanded(
child: Text( child: Text(
value, value,
@ -48,7 +51,7 @@ class DeviceManagementContent extends StatelessWidget {
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
), ),
const SizedBox(width: 8), const SizedBox(width: 12),
trailing ?? const SizedBox.shrink(), trailing ?? const SizedBox.shrink(),
], ],
), ),
@ -73,15 +76,15 @@ class DeviceManagementContent extends StatelessWidget {
); );
}, },
child: infoRow( child: infoRow(
label: 'Sub-Space:', label: 'Sub-Space:',
value: deviceInfo.subspace.subspaceName, value: deviceInfo.subspace.subspaceName,
valueColor: ColorsManager.textGray, valueColor: ColorsManager.blackColor,
trailing: const Icon( trailing: SvgPicture.asset(
Icons.arrow_forward_ios, Assets.arrowDown,
size: 16, width: 10,
color: ColorsManager.greyColor, height: 10,
), color: ColorsManager.greyColor,
), )),
), ),
), ),
const Divider(color: ColorsManager.dividerColor), const Divider(color: ColorsManager.dividerColor),
@ -104,7 +107,7 @@ class DeviceManagementContent extends StatelessWidget {
}, },
child: const Icon( child: const Icon(
Icons.copy, Icons.copy,
size: 16, size: 15,
color: ColorsManager.greyColor, color: ColorsManager.greyColor,
), ),
), ),

View File

@ -51,8 +51,7 @@ class DeviceSettingsPanel extends StatelessWidget {
Container( Container(
width: MediaQuery.of(context).size.width * 0.3, width: MediaQuery.of(context).size.width * 0.3,
color: ColorsManager.grey25, color: ColorsManager.grey25,
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.all(10),
horizontal: 20, vertical: 24),
child: ListView( child: ListView(
children: [ children: [
Row( Row(
@ -70,37 +69,43 @@ class DeviceSettingsPanel extends StatelessWidget {
children: [ children: [
Text( Text(
'Device Settings', 'Device Settings',
style: style: context.theme.textTheme.titleLarge!
context.theme.textTheme.titleLarge!.copyWith( .copyWith(
fontWeight: FontWeight.bold, fontWeight: FontWeight.w700,
color: ColorsManager.primaryColor, color: ColorsManager.vividBlue
), .withOpacity(0.7),
fontSize: 24),
), ),
], ],
), ),
const SizedBox(height: 24), const SizedBox(height: 24),
DefaultContainer( DefaultContainer(
borderRadius: BorderRadius.circular(15),
child: Row( child: Row(
children: [ children: [
CircleAvatar( Padding(
radius: 40, padding: const EdgeInsets.only(left: 15),
backgroundColor:
const Color.fromARGB(177, 213, 213, 213),
child: CircleAvatar( child: CircleAvatar(
backgroundColor: ColorsManager.whiteColors, radius: 38,
radius: 36, backgroundColor:
child: SvgPicture.asset( ColorsManager.grayBorder.withOpacity(0.5),
iconPath, child: CircleAvatar(
fit: BoxFit.cover, backgroundColor: ColorsManager.whiteColors,
radius: 36,
child: SvgPicture.asset(
iconPath,
fit: BoxFit.cover,
),
), ),
), ),
), ),
const SizedBox(width: 12), const SizedBox(width: 25),
Expanded( Expanded(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const SizedBox(height: 15),
Text( Text(
'Device Name:', 'Device Name:',
style: context.textTheme.bodyMedium! style: context.textTheme.bodyMedium!
@ -108,50 +113,79 @@ class DeviceSettingsPanel extends StatelessWidget {
color: ColorsManager.grayColor, color: ColorsManager.grayColor,
), ),
), ),
TextFormField( SizedBox(
maxLength: 30, height: 35,
style: const TextStyle( child: Row(
color: ColorsManager.blackColor, children: [
), SizedBox(
textAlign: TextAlign.start, height: 50,
focusNode: _bloc.focusNode, width: 190,
controller: _bloc.nameController, child: TextFormField(
enabled: _bloc.editName, scrollPadding: EdgeInsets.zero,
onFieldSubmitted: (value) { maxLength: 30,
_bloc.add(const ChangeNameEvent( style: const TextStyle(
value: false)); color: ColorsManager.blackColor,
}, fontSize: 16,
decoration: const InputDecoration( ),
border: InputBorder.none, textAlign: TextAlign.start,
fillColor: Colors.white10, focusNode: _bloc.focusNode,
counterText: '', controller: _bloc.nameController,
enabled: _bloc.editName,
onFieldSubmitted: (value) {
_bloc.add(const ChangeNameEvent(
value: false));
},
decoration: InputDecoration(
isDense: true,
contentPadding: EdgeInsets.zero,
border: InputBorder.none,
fillColor: Colors.white10,
counterText: '',
),
),
),
Column(
children: [
SizedBox(
width: 15,
height: 25,
child: Visibility(
visible:
_bloc.editName != true,
replacement: const SizedBox(),
child: InkWell(
onTap: () {
_bloc.add(
const ChangeNameEvent(
value: true));
},
child: SvgPicture.asset(
Assets
.editNameIconSettings,
color: ColorsManager
.lightGrayBorderColor,
height: 15,
width: 15,
),
),
),
),
],
),
],
), ),
), ),
], ],
), ),
), ),
const SizedBox(width: 8),
Visibility(
visible: _bloc.editName != true,
replacement: const SizedBox(),
child: GestureDetector(
onTap: () {
_bloc.add(
const ChangeNameEvent(value: true));
},
child: SvgPicture.asset(
Assets.editNameIconSettings,
color: ColorsManager.grayColor,
height: 20,
width: 20,
),
),
)
], ],
), ),
), ),
const SizedBox(height: 32), const SizedBox(height: 32),
Text('Device Management', style: sectionTitle), Padding(
padding: const EdgeInsets.only(left: 10),
child: Text('Device Management', style: sectionTitle),
),
DeviceManagementContent( DeviceManagementContent(
device: device, device: device,
subSpaces: subSpaces.cast<SubSpaceModel>(), subSpaces: subSpaces.cast<SubSpaceModel>(),

View File

@ -379,7 +379,7 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
} }
emit(GarageDoorLoadedState(status: deviceStatus)); emit(GarageDoorLoadedState(status: deviceStatus));
add(GarageDoorControlEvent( add(GarageDoorControlEvent(
deviceId: event.deviceId, deviceId: deviceId,
value: deviceStatus.delay.inSeconds, value: deviceStatus.delay.inSeconds,
code: 'countdown_1')); code: 'countdown_1'));
} catch (e) { } catch (e) {
@ -396,7 +396,7 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
_updateLocalValue(event.code, event.value); _updateLocalValue(event.code, event.value);
emit(GarageDoorLoadedState(status: deviceStatus)); emit(GarageDoorLoadedState(status: deviceStatus));
final success = await _runDeBouncer( final success = await _runDeBouncer(
deviceId: event.deviceId, deviceId: deviceId,
code: event.code, code: event.code,
value: event.value, value: event.value,
oldValue: oldValue, oldValue: oldValue,

View File

@ -30,12 +30,13 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
Future _fetchUserInfo(FetchUserInfo event, Emitter<HomeState> emit) async { Future _fetchUserInfo(FetchUserInfo event, Emitter<HomeState> emit) async {
try { try {
var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey); var uuid =
await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
user = await HomeApi().fetchUserInfo(uuid); user = await HomeApi().fetchUserInfo(uuid);
if (user != null && user!.project != null) { if (user != null && user!.project != null) {
await ProjectManager.setProjectUUID(user!.project!.uuid); await ProjectManager.setProjectUUID(user!.project!.uuid);
NavigationService.navigatorKey.currentContext!.read<SpaceTreeBloc>().add(InitialEvent());
} }
add(FetchTermEvent()); add(FetchTermEvent());
add(FetchPolicyEvent()); add(FetchPolicyEvent());
@ -67,10 +68,12 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
} }
} }
Future _confirmUserAgreement(ConfirmUserAgreementEvent event, Emitter<HomeState> emit) async { Future _confirmUserAgreement(
ConfirmUserAgreementEvent event, Emitter<HomeState> emit) async {
try { try {
emit(LoadingHome()); emit(LoadingHome());
var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey); var uuid =
await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
policy = await HomeApi().confirmUserAgreements(uuid); policy = await HomeApi().confirmUserAgreements(uuid);
emit(PolicyAgreement()); emit(PolicyAgreement());
} catch (e) { } catch (e) {
@ -123,5 +126,41 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
}, },
color: const Color(0xFF023DFE), color: const Color(0xFF023DFE),
), ),
// HomeItemModel(
// title: 'Move in',
// icon: Assets.moveinIcon,
// active: false,
// onPress: (context) {},
// color: ColorsManager.primaryColor,
// ),
// HomeItemModel(
// title: 'Construction',
// icon: Assets.constructionIcon,
// active: false,
// onPress: (context) {},
// color: ColorsManager.primaryColor,
// ),
// HomeItemModel(
// title: 'Energy',
// icon: Assets.energyIcon,
// active: false,
// onPress: (context) {},
// color: ColorsManager.slidingBlueColor.withOpacity(0.2),
// ),
// HomeItemModel(
// title: 'Integrations',
// icon: Assets.integrationsIcon,
// active: false,
// onPress: (context) {},
// color: ColorsManager.slidingBlueColor.withOpacity(0.2),
// ),
// HomeItemModel(
// title: 'Asset',
// icon: Assets.assetIcon,
// active: false,
// onPress: (context) {},
// color: ColorsManager.slidingBlueColor.withOpacity(0.2),
// ),
]; ];
} }

View File

@ -20,12 +20,7 @@ class _HomeWebPageState extends State<HomeWebPage> {
// Flag to track whether the dialog is already shown. // Flag to track whether the dialog is already shown.
bool _dialogShown = false; bool _dialogShown = false;
@override
void initState() {
super.initState();
final homeBloc = BlocProvider.of<HomeBloc>(context);
homeBloc.add(const FetchUserInfo());
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -38,8 +33,10 @@ class _HomeWebPageState extends State<HomeWebPage> {
child: BlocConsumer<HomeBloc, HomeState>( child: BlocConsumer<HomeBloc, HomeState>(
listener: (BuildContext context, state) { listener: (BuildContext context, state) {
if (state is HomeInitial) { if (state is HomeInitial) {
if (homeBloc.user!.hasAcceptedWebAgreement == false && !_dialogShown) { if (homeBloc.user!.hasAcceptedWebAgreement == false &&
_dialogShown = true; // Set the flag to true to indicate the dialog is showing. !_dialogShown) {
_dialogShown =
true; // Set the flag to true to indicate the dialog is showing.
Future.delayed(const Duration(seconds: 1), () { Future.delayed(const Duration(seconds: 1), () {
showDialog( showDialog(
context: context, context: context,
@ -54,7 +51,7 @@ class _HomeWebPageState extends State<HomeWebPage> {
_dialogShown = false; _dialogShown = false;
if (v != null) { if (v != null) {
homeBloc.add(ConfirmUserAgreementEvent()); homeBloc.add(ConfirmUserAgreementEvent());
homeBloc.add(const FetchUserInfo()); // homeBloc.add(const FetchUserInfo());
} }
}); });
}); });
@ -98,7 +95,8 @@ class _HomeWebPageState extends State<HomeWebPage> {
width: size.width * 0.68, width: size.width * 0.68,
child: GridView.builder( child: GridView.builder(
itemCount: homeBloc.homeItems.length, itemCount: homeBloc.homeItems.length,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, // Adjust as needed. crossAxisCount: 3, // Adjust as needed.
crossAxisSpacing: 20.0, crossAxisSpacing: 20.0,
mainAxisSpacing: 20.0, mainAxisSpacing: 20.0,
@ -111,7 +109,8 @@ class _HomeWebPageState extends State<HomeWebPage> {
active: homeBloc.homeItems[index].active!, active: homeBloc.homeItems[index].active!,
name: homeBloc.homeItems[index].title!, name: homeBloc.homeItems[index].title!,
img: homeBloc.homeItems[index].icon!, img: homeBloc.homeItems[index].icon!,
onTap: () => homeBloc.homeItems[index].onPress(context), onTap: () =>
homeBloc.homeItems[index].onPress(context),
); );
}, },
), ),

View File

@ -11,7 +11,6 @@ class CreateRoutineBloc extends Bloc<CreateRoutineEvent, CreateRoutineState> {
on<SpaceOnlyWithDevicesEvent>(_fetchSpaceOnlyWithDevices); on<SpaceOnlyWithDevicesEvent>(_fetchSpaceOnlyWithDevices);
on<SaveCommunityIdAndSpaceIdEvent>(saveSpaceIdCommunityId); on<SaveCommunityIdAndSpaceIdEvent>(saveSpaceIdCommunityId);
on<ResetSelectedEvent>(resetSelected); on<ResetSelectedEvent>(resetSelected);
on<FetchCommunityEvent>(_fetchCommunity);
} }
String selectedSpaceId = ''; String selectedSpaceId = '';
@ -50,18 +49,4 @@ class CreateRoutineBloc extends Bloc<CreateRoutineEvent, CreateRoutineState> {
selectedCommunityId = ''; selectedCommunityId = '';
emit(const ResetSelectedState()); emit(const ResetSelectedState());
} }
Future<void> _fetchCommunity(
FetchCommunityEvent event, Emitter<CreateRoutineState> emit) async {
emit(const CommunitiesLoadingState());
try {
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
communities =
await CommunitySpaceManagementApi().fetchCommunities(projectUuid);
emit(const CommunityLoadedState());
} catch (e) {
emit(SpaceTreeErrorState('Error loading communities $e'));
}
}
} }

View File

@ -43,9 +43,3 @@ class ResetSelectedEvent extends CreateRoutineEvent {
} }
class FetchCommunityEvent extends CreateRoutineEvent {
const FetchCommunityEvent();
@override
List<Object> get props => [];
}

View File

@ -1,29 +1,66 @@
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routines/create_new_routines/dropdown_menu_content.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'space_tree_dropdown_bloc.dart';
class CommunityDropdown extends StatelessWidget { class SpaceTreeDropdown extends StatelessWidget {
final String? selectedValue; final String? selectedSpaceId;
final List<CommunityModel> communities; final Function(String?)? onChanged;
final Function(String?) onChanged;
final TextEditingController _searchController = TextEditingController();
CommunityDropdown({ const SpaceTreeDropdown({
Key? key, super.key,
required this.selectedValue, this.selectedSpaceId,
required this.onChanged, this.onChanged,
required this.communities, });
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( return BlocProvider(
padding: const EdgeInsets.all(10.0), create: (context) {
child: Column( final bloc = SpaceTreeDropdownBloc(selectedSpaceId);
crossAxisAlignment: CrossAxisAlignment.start, bloc.add(FetchSpacesEvent());
children: [ return bloc;
Text( },
child: _DropdownContent(onChanged: onChanged),
);
}
}
class _DropdownContent extends StatefulWidget {
final Function(String?)? onChanged;
const _DropdownContent({this.onChanged});
@override
State<_DropdownContent> createState() => _DropdownContentState();
}
class _DropdownContentState extends State<_DropdownContent> {
final LayerLink _layerLink = LayerLink();
OverlayEntry? _overlayEntry;
@override
void dispose() {
_removeOverlay();
super.dispose();
}
void _removeOverlay() {
_overlayEntry?.remove();
_overlayEntry = null;
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Text(
"Community", "Community",
style: Theme.of(context).textTheme.bodyMedium!.copyWith( style: Theme.of(context).textTheme.bodyMedium!.copyWith(
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
@ -31,126 +68,149 @@ class CommunityDropdown extends StatelessWidget {
color: ColorsManager.blackColor, color: ColorsManager.blackColor,
), ),
), ),
const SizedBox(height: 8), ),
SizedBox( CompositedTransformTarget(
child: Container( link: _layerLink,
decoration: BoxDecoration( child: GestureDetector(
borderRadius: BorderRadius.circular(10), onTap: () => _toggleDropdown(context),
), child: BlocBuilder<SpaceTreeDropdownBloc, SpaceTreeDropdownState>(
child: DropdownButton2<String>( builder: (context, state) {
underline: const SizedBox(), return _buildDropdownTrigger(state);
value: selectedValue,
items: communities.map((community) {
return DropdownMenuItem<String>(
value: community.uuid,
child: Text(
' ${community.name}',
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
);
}).toList(),
onChanged: onChanged,
style: const TextStyle(color: Colors.black),
hint: Padding(
padding: const EdgeInsets.only(left: 10),
child: Text(
" Please Select",
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.textGray,
),
),
),
customButton: Container(
height: 45,
decoration: BoxDecoration(
border: Border.all(color: ColorsManager.textGray, width: 1.0),
borderRadius: BorderRadius.circular(10),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 5,
child: Text(
selectedValue != null
? " ${communities.firstWhere((element) => element.uuid == selectedValue).name}"
: ' Please Select',
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: selectedValue != null
? Colors.black
: ColorsManager.textGray,
),
overflow: TextOverflow.ellipsis,
),
),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: const BorderRadius.only(
topRight: Radius.circular(10),
bottomRight: Radius.circular(10),
),
),
height: 45,
child: const Icon(
Icons.keyboard_arrow_down,
color: ColorsManager.textGray,
),
),
),
],
),
),
dropdownStyleData: DropdownStyleData(
maxHeight: MediaQuery.of(context).size.height * 0.4,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
),
),
dropdownSearchData: DropdownSearchData(
searchController: _searchController,
searchInnerWidgetHeight: 50,
searchInnerWidget: Container(
height: 50,
padding:
const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
child: TextFormField(
style: const TextStyle(color: Colors.black),
controller: _searchController,
decoration: InputDecoration(
isDense: true,
contentPadding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 12,
),
hintText: 'Search for community...',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
),
),
),
searchMatchFn: (item, searchValue) {
final communityName =
(item.child as Text).data?.toLowerCase() ?? '';
return communityName
.contains(searchValue.toLowerCase().trim());
},
),
onMenuStateChange: (isOpen) {
if (!isOpen) {
_searchController.clear();
}
}, },
menuItemStyleData: const MenuItemStyleData( ),
height: 40, ),
),
],
);
}
Widget _buildDropdownTrigger(SpaceTreeDropdownState state) {
if (state.status == SpaceTreeDropdownStatus.loading) {
return Container(
height: 46,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade300),
borderRadius: BorderRadius.circular(12),
),
margin: const EdgeInsets.symmetric(horizontal: 10),
child: const Center(child: CircularProgressIndicator()),
);
}
if (state.status == SpaceTreeDropdownStatus.failure) {
return Container(
height: 46,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade300),
borderRadius: BorderRadius.circular(12),
),
margin: const EdgeInsets.symmetric(horizontal: 10),
child: Center(
child: Text(
'Error: ${state.errorMessage}',
style: const TextStyle(color: Colors.red),
),
),
);
}
final selectedCommunity = _findCommunity(state, state.selectedSpaceId);
return Container(
height: 46,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade300),
borderRadius: BorderRadius.circular(12),
),
margin: const EdgeInsets.symmetric(horizontal: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Text(
selectedCommunity?.name ?? 'Please Select',
style: TextStyle(
color: selectedCommunity != null
? ColorsManager.blackColor
: ColorsManager.textGray,
overflow: TextOverflow.ellipsis,
fontWeight: FontWeight.w400,
fontSize: 13,
), ),
), ),
)) ),
Container(
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: const BorderRadius.only(
topRight: Radius.circular(10),
bottomRight: Radius.circular(10),
),
),
height: 45,
width: 33,
child: const Icon(
Icons.keyboard_arrow_down,
color: ColorsManager.textGray,
),
),
], ],
), ),
); );
} }
void _toggleDropdown(BuildContext context) {
if (_overlayEntry != null) {
_removeOverlay();
return;
}
final bloc = context.read<SpaceTreeDropdownBloc>();
_overlayEntry = OverlayEntry(
builder: (context) => Positioned(
width: 300,
child: CompositedTransformFollower(
link: _layerLink,
showWhenUnlinked: false,
offset: const Offset(0, 48),
child: Material(
color: ColorsManager.whiteColors,
elevation: 8,
borderRadius: BorderRadius.circular(12),
child: BlocProvider.value(
value: bloc,
child: DropdownMenuContent(
selectedSpaceId: bloc.state.selectedSpaceId,
onChanged: (id) {
if (id != null && mounted) {
bloc.add(SpaceTreeDropdownSelectEvent(id));
widget.onChanged?.call(id);
_removeOverlay();
}
},
onClose: _removeOverlay,
),
),
),
),
),
);
Overlay.of(context).insert(_overlayEntry!);
}
CommunityModel? _findCommunity(
SpaceTreeDropdownState state, String? communityId) {
if (communityId == null) return null;
try {
return state.filteredCommunities.firstWhere((c) => c.uuid == communityId);
} catch (_) {}
try {
return state.communities.firstWhere((c) => c.uuid == communityId);
} catch (e) {
return null;
}
}
} }

View File

@ -18,19 +18,19 @@ class CreateNewRoutinesDialog extends StatefulWidget {
class _CreateNewRoutinesDialogState extends State<CreateNewRoutinesDialog> { class _CreateNewRoutinesDialogState extends State<CreateNewRoutinesDialog> {
String? _selectedCommunity; String? _selectedCommunity;
String? _selectedSpace; String? _selectedSpace;
String? _selectedId;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (BuildContext context) => create: (BuildContext context) => CreateRoutineBloc(),
CreateRoutineBloc()..add(const FetchCommunityEvent()),
child: BlocBuilder<CreateRoutineBloc, CreateRoutineState>( child: BlocBuilder<CreateRoutineBloc, CreateRoutineState>(
builder: (context, state) { builder: (context, state) {
final _bloc = BlocProvider.of<CreateRoutineBloc>(context); final _bloc = BlocProvider.of<CreateRoutineBloc>(context);
final spaces = _bloc.spacesOnlyWithDevices; final spaces = _bloc.spacesOnlyWithDevices;
final isLoadingCommunities = state is CommunitiesLoadingState; final isLoadingCommunities = state is CommunitiesLoadingState;
final isLoadingSpaces = state is SpaceWithDeviceLoadingState; final isLoadingSpaces = state is SpaceWithDeviceLoadingState;
String spaceHint = 'Select a community first'; String spaceHint = 'Please Select';
if (_selectedCommunity != null) { if (_selectedCommunity != null) {
if (isLoadingSpaces) { if (isLoadingSpaces) {
spaceHint = 'Loading spaces...'; spaceHint = 'Loading spaces...';
@ -40,7 +40,10 @@ class _CreateNewRoutinesDialogState extends State<CreateNewRoutinesDialog> {
spaceHint = 'Select Space'; spaceHint = 'Select Space';
} }
} }
if (_selectedId != null && _selectedCommunity != _selectedId) {
_selectedSpace = null;
_selectedCommunity = _selectedId;
}
return AlertDialog( return AlertDialog(
backgroundColor: Colors.white, backgroundColor: Colors.white,
insetPadding: EdgeInsets.zero, insetPadding: EdgeInsets.zero,
@ -51,7 +54,9 @@ class _CreateNewRoutinesDialogState extends State<CreateNewRoutinesDialog> {
'Create New Routines', 'Create New Routines',
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyMedium!.copyWith( style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: ColorsManager.primaryColor, color: ColorsManager.spaceColor,
fontSize: 20,
fontWeight: FontWeight.w700,
), ),
), ),
content: Stack( content: Stack(
@ -60,40 +65,44 @@ class _CreateNewRoutinesDialogState extends State<CreateNewRoutinesDialog> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
const Divider(), const Divider(),
Padding( const SizedBox(height: 20),
padding: const EdgeInsets.only(left: 15, right: 15), Column(
child: CommunityDropdown( children: [
communities: _bloc.communities..sort( Padding(
(a, b) => a.name.toLowerCase().compareTo( padding:
b.name.toLowerCase(), const EdgeInsets.only(left: 13, right: 8),
child: Column(
children: [
SpaceTreeDropdown(
selectedSpaceId: _selectedId,
onChanged: (String? newValue) {
setState(() => _selectedId = newValue!);
if (_selectedId != null) {
_bloc.add(SpaceOnlyWithDevicesEvent(
_selectedId!));
}
},
), ),
],
)),
const SizedBox(height: 5),
const SizedBox(height: 8),
Padding(
padding: const EdgeInsets.only(left: 15, right: 15),
child: SpaceDropdown(
hintMessage: spaceHint,
spaces: spaces,
selectedValue: _selectedSpace,
onChanged: (String? newValue) {
setState(() {
_selectedSpace = newValue;
});
},
), ),
selectedValue: _selectedCommunity, ),
onChanged: (String? newValue) { ],
setState(() {
_selectedCommunity = newValue;
_selectedSpace = null;
});
if (newValue != null) {
_bloc.add(SpaceOnlyWithDevicesEvent(newValue));
}
},
),
),
const SizedBox(height: 5),
Padding(
padding: const EdgeInsets.only(left: 15, right: 15),
child: SpaceDropdown(
hintMessage: spaceHint,
spaces: spaces,
selectedValue: _selectedSpace,
onChanged: (String? newValue) {
setState(() {
_selectedSpace = newValue;
});
},
),
), ),
const SizedBox(height: 20),
const Divider(), const Divider(),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisAlignment: MainAxisAlignment.spaceAround,

Some files were not shown because too many files have changed in this diff Show More