50 Commits
Author SHA1 Message Date
pei 94138ba7f4 test(e2e): mobile 视口测试 (375x812) + 扩展登录态路由
完整测试覆盖 (49 路由, 0 崩溃):
- 公开 desktop: 18/18 ✓
- 登录态 desktop: 17/17 ✓ (含 orderdetail/paynow/view-ticket/ocr-scan/renew-*)
- mobile 视口: 14/14 ✓ (仅 /me 4px RenderFlex 溢出, 无害布局警告)

修复汇总 (本轮自动化发现+修复):
1. download Scrollbar 缺 ScrollPosition -> primary:true
2. contact-stores initState dispose 后 setState -> mounted 保护
3. buy-service onGenerateRoute pathElements 越界 RangeError -> 长度检查
4. add_remove_button/shopping_cart_* cartInfo 误加 ! (nullfix 脚本)
5. checkout table_token(tableNumber!) 无判空
2026-08-03 02:01:17 +08:00
pei 33b54fe454 feat(e2e): autologin patch (dev) + 登录态路由测试脚本
- util_web devAutologin: localStorage[_test_token]=user|pass -> 登录API写Hive+dispatch currentUser
- 延迟3s执行等 Flutter/Hive ready (否则 httpPost hang)
- main.dart 调用 devAutologin
- run_auth.js: 注入token遍历登录态路由
- 已验证: autologin API 200 OK
2026-08-03 01:50:12 +08:00
pei 901e42a41b fix(runtime): onGenerateRoute pathElements 越界 RangeError
- buy-service/renew-minioffice 加长度检查 (pathElements.length >= 4/3)
- 根因: Flutter web 深链接渐进式路径解析, onGenerateRoute 被调用多次,
  pathElements 递增 ([,buy-service] -> [,buy-service,1] -> 完整),
  前几次路径短但 pathElements[1]已匹配 -> int.parse([2])/[3] 越界
- 直接访问/刷新 /buy-service/x/y, /renew-minioffice/x 时崩溃
- 恢复 buy_service 实验代码 (data 校验 + mounted 保留)
2026-08-02 00:13:33 +08:00
pei af8934fe7f diag: FlutterError.onError 加 CK_CTX (widget 上下文) 定位 RangeError 来源 2026-08-01 23:35:34 +08:00
pei 048c5a9ff4 fix(runtime): contact-stores initState httpGet.then setState 加 mounted 保护 (dispose 后 setState) 2026-08-01 23:29:08 +08:00
pei 1d4028f486 fix(compile): buy_service value cast Map<String,dynamic>.from; gitignore e2e node_modules 2026-08-01 23:26:14 +08:00
pei 944493a39b fix(runtime): e2e 发现的 3 个 bug 修复
- download: desktop_download_apps SingleChildScrollView 加 primary:true (Scrollbar 缺 ScrollPosition)
- contact-stores: checkDomainAvailability async 后 setState 加 mounted 保护 (dispose 后 setState)
- buy-service: _loadData 加 data 结构校验 + mounted 保护 (API 400 无效参数时 data 为错误结构 -> RangeError)
2026-08-01 23:20:25 +08:00
pei 6d08db54a5 chore: 清理 checkout mainBody 的 'aaa:' 调试 print 2026-08-01 02:38:15 +08:00
pei 3f9256491d fix(runtime): checkout table_token(store.state.tableNumber!) -> tableNumber ?? ''. 普通网购用户无餐桌号(null)时崩溃. desktop L309/mobile L284. Fixes checkout/310 Unexpected null value 2026-08-01 02:36:01 +08:00
pei 95e40f31cc fix(runtime): 同类 nullfix 脚本误加 ! 全库修复 - getCartInfoByBusiness 返回可空但末尾误加 !, 后接 if(x!=null) 判空. 影响: shopping_cart_bar/shopping_cart_widget/desktop_shopping_cart_widget(可空目标去!); shop_products/mobile shop(非空声明改 CartInfo?) 2026-08-01 02:27:50 +08:00
pei 639d2033f0 fix(runtime): add_remove_button cartInfo 误加 ! (nullfix 脚本) -> 去掉. getCartInfoByBusiness 返回可空, 购物车空时 ! 崩溃 -> AddRemoveButton build L197 Unexpected null value. 修复 /shop 商品列表和 /checkout lineItem 的 +/- 按钮崩溃 2026-08-01 02:22:26 +08:00
pei 4da7fb32de wip: checkout mainBody diagnostic print (CK_DEBUG) + shippingTime null-safe 2026-08-01 02:14:52 +08:00
pei 147ab866e1 fix(runtime): late top-level/instance vars used with ??= (mediaQuery/screenHeight/etc) -> nullable. Fixes LateInitializationError on /me /shop /product-detail 2026-08-01 02:06:07 +08:00
pei 0526baa3c8 fix(runtime): 37 late fields with == null checks were wrongly migrated -> nullable. Fixes LateInitializationError crashes on page navigation (shop/checkout/comment/data pages) 2026-08-01 01:58:36 +08:00
pei b49fb59db4 fix(home): Scrollbar+SingleChildScrollView primary:true (no ScrollPosition runtime error); docs: runtime issues in TODO §9 2026-08-01 01:53:05 +08:00
pei 9608e8b9fb docs: WEB BUILD SUCCEEDS. build_web.sh helper, TODO status update. lib 6 (util_io deferred), web 0 errors 2026-08-01 01:29:50 +08:00
pei 5ccc06b0f7 phase3: WEB BUILD SUCCEEDS. cross_file override (0.3.4+2, Dart3-safe), parabolic/popup _margin EdgeInsets, remaining nullable fixes. lib 12->6(util_io deferred), web build OK with --no-tree-shake-icons 2026-08-01 01:27:51 +08:00
pei 7c69197396 phase3: nullable fields/methods, casts, ?.call, pinput/YoutubePlayer v5, buttonColor, dead-code removal. 72->16 2026-08-01 01:21:37 +08:00
pei 137eca4c69 phase3: nullable fields/methods, casts, ?.call, condition fixes across 11 files. 108->72 2026-08-01 01:16:25 +08:00
pei b8b70a87f9 docs: add TODO.md for resuming Dart 3 null-safety migration (118->0 remaining) 2026-07-31 15:10:16 +08:00
pei 3053246bb8 phase3: mobile/shop clean (categoryDescHeight double, FooterBuilder LoadStatus?, nullable fixes); edit_address .buttonColor->colorScheme.primary. 131->118 2026-07-31 15:09:29 +08:00
pei 5cb5ef6396 phase3: checkout files clean (nullable fields, ternary/concat/condition fixes). 142->131 2026-07-31 15:05:08 +08:00
pei a6d5b9cd2d phase3: fix attribute widgets (qty/check/radio) - prefix-! bug, multi-line toUpperCase, required conditions. ~30 fixed 2026-07-31 15:00:04 +08:00
pei 18abf4eb82 phase3: FIX arg-bang regex (missing \] in char class skipped subscripts). 235->183 2026-07-31 14:57:23 +08:00
pei 70076d71c1 phase3: shop.dart NotificationListener return bool 2026-07-31 14:54:32 +08:00
pei 6487c0db54 phase3: pinput v5, late field fix, carousel nullable, badges badgeAnimation param. 251->242 2026-07-31 14:53:58 +08:00
pei ab06fadea8 phase3: @required->required keyword, nullable for-in iterator fix. 309->251 2026-07-31 14:49:02 +08:00
pei 1aa7cf3477 phase3: targeted local-var nullable (strict type) + nullfix cascade. 379->309 2026-07-26 10:47:55 +08:00
pei 3ed58e1596 phase3: precise nullable-condition fixes (if(x)->if(x==true), analyzer-driven). 399->379 2026-07-26 10:46:26 +08:00
pei 97e4908126 phase3: BreadCrumb.route nullable (+stable nullfix re-run). 440->399 2026-07-26 10:44:45 +08:00
pei 154d696e70 phase3: improve arg-bang handler (allow ! in chains, ; terminator). 574->440 2026-07-26 10:41:02 +08:00
pei 36f36b815f phase3: youtube_player_iframe 2.x->5.x migration (fromVideoId) 2026-07-26 01:11:47 +08:00
pei 6d789c7b19 phase3: badges 2.x->3.x migration (badgeStyle/animation), SearchBar/onPrimary fixes. 596->580 2026-07-26 01:10:45 +08:00
pei cdaaa63d67 phase3: stabilize nullfix.py (disable risky local-nullable handler)
Script stable handlers (zero corruption): bang(!), late, param-nullable,
field-formal field-nullable, arg-bang. Reusable — re-run after manual fixes.
Errors: 2374(peak) -> 596 | web build: 1845 -> 571
2026-07-26 00:15:38 +08:00
pei f1d7dbb423 phase3: fix Scrollbar isAlwaysShown->thumbVisibility, badges hide Badge. 621->605 2026-07-25 18:17:33 +08:00
pei a76b872966 phase3: nullfix arg-bang handler (argument_type/invalid_assignment). 872 -> 621 2026-07-25 18:16:40 +08:00
pei c21ccbd54d phase3: nullfix field-formal field-nullable handler. 907 -> 872 2026-07-25 18:14:55 +08:00
pei fce670664b phase3: nullfix.py batch script — bang/late/param-nullable
Automated null-safety fixes driven by dart analyze (no corruption):
- unchecked_use_of_nullable_value: insert '!' on receiver (property/method/[]/op)
- not_initialized field/var: mark 'late'
- missing_default_value_for_parameter: nullable param
Errors: 2374(peak) -> 907
2026-07-25 18:13:01 +08:00
pei 8f3d3509ea phase3(wip): desktop_checkout field null-safety + build local-shadow 2026-07-25 02:53:03 +08:00
pei e2f0d37edd phase3: generated l10n/messages_all, events, actions, dialog null-safe 2026-07-24 20:30:00 +08:00
pei 1f85ae1e63 phase3: bulk null-safety fixes
- validator: (String value) -> (String? value) [30 files]
- ElevatedButton.styleFrom(primary:) -> backgroundColor: [31 files]
- global Key? param fix [129 files]
2026-07-24 20:27:16 +08:00
pei e2f815e141 phase3: util_web + shop_scroll (custom scroll) null-safe; global Key? param fix 2026-07-24 20:24:57 +08:00
pei f831fd1405 phase3: util_web null-safe (showImage, WebImagePicker, ImageInfo)
util_io deferred (excluded from web build via conditional import).
2026-07-24 20:17:07 +08:00
pei 7e8182259f phase3: utils.dart null-safe (cart logic + dio5 error handling)
- cart event handlers rewritten with local list + nullable model fields
- getCartInfo*/addCart/removeCart helpers: nullable List<CartInfo>? params
- addSubproductToCard/addSubproductQty/removeSubproduct: null-safe nested access
- showMessageDialog: DioException + promoted response local
- newCartLineItem params nullable; getWeekDayName default return
- launchURL->launch; RuntimeError code nullable
2026-07-24 20:13:07 +08:00
pei 88dd90ed7c phase3(critical-path): home page chain null-safe
home.dart + desktop/mobile navigation, carousels, index content widgets,
customers_logo, appbar_menu, navigation_drawer, MobileBottomNav, double_back.
Fixes: Key? params, nullable State fields, Scrollbar thumbVisibility,
ModalRoute.of()?, badges hide Badge, cartInfos local promotion.
2026-07-24 13:42:03 +08:00
pei ae4c4046c3 phase3(critical-path): store + main + routes + nav components null-safe
- store/state + reducers: nullable AppState fields & reducer types
- main.dart: localeResolutionCallback Locale?, settings.name? guard
- routes.dart: fluro 2.0.5 HandlerFunc (BuildContext?) + params['x']!
- navigationbar/breadcrumbs/bottom_nav/text_link: nullable optional params/fields
2026-07-24 13:37:04 +08:00
pei cef00db911 phase3: null-safe store/ (AppState fields + reducers nullable) 2026-07-24 13:31:34 +08:00
pei 4f9aa4f683 phase3(foundation): http_util dio5 migration + null-safe models
- http_util.dart: dio4->5 (DioException, nullable params, drop unused statusCode,
  null-safe e.response!.data), countryCode ?? ''
- models/* (39 files): make all instance fields nullable (fromJson initializer-list
  pattern forces nullable); fix internal method usages (cart_info/cart_line_item/
  order/shipping_rate) with !/??
- models/ now passes dart analyze with 0 errors

Widget-level null-safety + remaining utils/store continue in next batch.
2026-07-24 03:48:54 +08:00
pei 1a578c925d feat: Phase 2 — upgrade deps to null-safe, replace deprecated packages
- pubspec: bump all maintained deps to null-safe latest; flutter pub get resolves
- Remove 12 packages (0-ref or no null-safe): splashscreen, flappy_search_bar,
  searchable_dropdown, share, platform_detect, flutter_inappwebview, countdown,
  gender_selection, flutter_dash, smooth_star_rating, hovering, ffi
- Add flutter_rating_bar
- Keep discontinued-but-null-safe for now (Phase 5): pull_to_refresh, hive, catcher
- New null-safe custom components (API-compatible, callers change only imports):
  utils/countdown.dart, widgets/general/{hover_widget,gender_selection,
  smooth_star_rating,search_bar}.dart
- main.dart: drop dead SplashScreen _buildBody + _to field
- 23 consuming files: swap deprecated imports to local components

Null-safety migration + upgraded-API adaptation = Phase 3.
2026-07-24 03:10:12 +08:00
pei 7ffcc848d0 feat: Phase 1 — remove Stripe, switch to e-Transfer
- Drop stripe_payment + stripe_sdk deps; delete stripe pay pages/widgets
- New ETransferPay widget: shows payment@wisetronic.com + R#<orderId> remark
- goPayment stripe/native branches now route to e-Transfer
- pay_now widgets: strip saved-cards section & dead nativePay logic
- my_cards pages rewritten as e-Transfer info (route kept)
- models/utils/constants cleaned of stripe; env constraint -> Dart 3

See UPGRADE_NOTES.md. (Null-safety migration is Phase 3; deps upgrade Phase 2.)
2026-07-24 02:47:13 +08:00
290 changed files with 6098 additions and 4962 deletions
+250
View File
@@ -0,0 +1,250 @@
# TODO — Flutter Wisetronic Dart 3 空安全迁移
> ## ✅ Web 构建已成功!(2026-08-01)
> **`flutter build web --no-tree-shake-icons` → ✓ Built build/web/(main.dart.js 4.5M)**
> - `dart analyze lib`: 仅剩 **6 error**,全部在 `utils/util_io.dart`(原生路径,Web 已排除,见 §5 延后)。
> - Web 可达错误: **0**。
> - 峰值 2374 → 6(全部 util_io 原生)。0 语法损坏。分支 `dev2`。
> - 构建脚本: `./build_web.sh`(构建)/ `./build_web.sh run`(Chrome 运行)。
> - **关键修复**: `cross_file` override 到 `0.3.4+2`(旧版 0.3.1+4 用了 Dart3 移除的 `UnmodifiableUint8ListView`;0.3.5+ 需 Dart 3.10)。
---
## 0. 快速恢复(Resume 起点)
```bash
cd /Users/peima/StudioProjects/flutter_wisetronic
git log --oneline -1 # 确认在最新提交
dart analyze lib | tail -5 # 当前: 仅 6 error(util_io.dart)
./build_web.sh # 构建: ✓ Built build/web/
./build_web.sh run # Chrome 运行调试
# 重跑自动修复脚本(安全,带损坏自检,可随时跑)—— 已无 web 可达错误,通常无需再跑
python3 tools/nullfix.py --max-rounds 12
```
**核心原则**:每次改动后用 `dart analyze lib | grep -cE '\s+error\s+-'` 数错误;脚本若报"检测到语法损坏"会自动中止,`git checkout -- lib` 回滚。
---
## 1. 剩余错误分布(118 个)
| 规则 | 数量 | 说明 |
|------|------|------|
| `unchecked_use_of_nullable_value` | 44 | 可空值当非空用(方法调用/条件/迭代器,多为多行) |
| `invalid_assignment` | 34 | 赋值类型不匹配(复杂表达式) |
| `argument_type_not_assignable` | 22 | 参数类型不匹配(三元/比较/Map字面量) |
| `return_of_invalid_type_from_closure` | 4 | 闭包返回类型 |
| `undefined_getter` | 3 | 多为 `.buttonColor`(Flutter 3 移除) |
| `return_of_invalid_type` | 3 | 函数 `return null` 但返回类型非空 |
| `undefined_named_parameter` | 2 | |
| `undefined_method` | 2 | |
| `creation_with_non_type` | 2 | 类名拼错(util_io 内) |
| `extra_positional_arguments_could_be_named` | 1 | |
| `body_might_complete_normally` | 1 | |
**错误最多的文件**(详细见 `dart analyze lib`):
```
6 utils/util_io.dart ← 延后(仅原生,Web 构建已排除)
5 widgets/desktop/desktop_edit_address.dart ← .trim() 多行(见 §3,已知修法)
5 widgets/mobile/mobile_edit_address.dart ← 同上
5 widgets/general/add_remove_button.dart
5 widgets/general/parabolic_animation_widget.dart
5 widgets/general/sliding_up_panel.dart
4 widgets/desktop/desktop_me.dart
4 widgets/mobile/mobile_attribute_selection.dart
4 widgets/mobile/mobile_order_detail.dart
3 widgets/desktop/desktop_coupons.dart / desktop_my_support / desktop_order_detail / shop_products
3 widgets/general/animation_point_manager / popup_animation_widget
3 widgets/mobile/mobile_coupons / mobile_me / mobile_my_support / mobile_orders / shopping_cart_bar
2 约 12 个文件(blog/orders/product_item/shopping_cart 等)
1 约 25 个文件(单点错误)
```
---
## 2. 推荐处理顺序
1. **edit_address(5+5)** — 已知修法,见 §3,最快。
2. **parabolic/popup_animation(5+3)** — `late` 字段已修,可能还有 unchecked_use(offset 计算方法调用),手动看。
3. **sliding_up_panel(5)** — 第三方面板 widget 适配,手动。
4. **add_remove_button(5)** — badges 相关,手动。
5. **散落的 2-error / 1-error 文件** — 用 `dart analyze lib/<file>` 逐个看,多为加 `!`。
6. **util_io.dart(6)** — 最后处理(见 §5),不影响 Web 构建。
**目标**:先清掉 Web 可达错误(`flutter build web` 的 112),让 Web 能跑;`util_io` 原生路径可延后。
---
## 3. 已知具体修法(直接套用)
### 3.1 edit_address `.trim()` 多行(desktop + mobile,各 5 处)
错误:`A nullable expression can't be used to invoke 'trim'`。代码结构:
```dart
validator: (String? value) {
if (value // ← value 是 String?
.trim()
.isEmpty) {
```
**修法**:把 `if (value` 行改成 `if (value!`。
```python
# 上次脚本 bug:用了 rstrip() 应该用 strip()。正确版:
for p in ['lib/widgets/desktop/desktop_edit_address.dart','lib/widgets/mobile/mobile_edit_address.dart']:
lines=open(p).read().split('\n'); n=0
for i in range(len(lines)):
if lines[i].strip()=='if (value' and lines[i+1].lstrip().startswith('.trim()'):
lines[i]=lines[i].rstrip()+'!'; n+=1 # 注意 rstrip() 保留前导缩进
open(p,'w').write('\n'.join(lines))
```
(`.buttonColor`→`.colorScheme.primary` 已在两个文件修好。)
### 3.2 通用模式(手动加 `!` / `?? 默认` / `== true`)
- `String? → String` 参数:`field` → `field!`(确认运行时非空)。
- `num?/int?/double?` 比较:`subtotal > minPrice` → `subtotal > minPrice!` 或 `(minPrice ?? 0)`。
- `bool?` 当条件:`if (x)` → `if (x == true)`;`if (!x)` → `if (x != true)`。
- `return null;` 但返回类型非空:把函数返回类型加 `?`(如 `CategoryProducts? foo()`)。
- 局部变量赋值 nullable:声明加 `?`(如 `Map<String,dynamic>? x = ...`),下游 nullfix 会补 `!`。
- 多行方法调用 `.toUpperCase()` / `.trim()`:接收者在上一行末尾,在该行末尾加 `!`。
### 3.3 可复用的定向脚本(一次性,贴进 bash 跑)
**a) 条件修复(analyzer 驱动,只修简单 `if (chain)`)** — 已用过,安全:
```python
python3 -c "
import re,subprocess
ERR=re.compile(r'\s+error\s+-\s+([\w/.\-]+):(\d+):(\d+)\s+-\s+(.*?)\s+-\s+([a-z_]+)\s*\$')
pat=re.compile(r'^(\s*if \()(!?)([\w.!\[\]]+)(\)\s*\{?\s*)\$')
out=subprocess.run(['dart','analyze','lib'],capture_output=True,text=True).stdout
tg={}
for ln in out.splitlines():
m=ERR.match(ln)
if m and 'used as a condition' in m.group(4): tg.setdefault('lib/'+m.group(1),set()).add(int(m.group(2)))
n=0
for p,ls in tg.items():
L=open(p).read().split('\n');ch=False
for i,x in enumerate(L,1):
if i in ls:
m=pat.match(x.rstrip('\n'))
if m: L[i-1]=m.group(1)+m.group(3)+(' != true' if m.group(2) else ' == true')+m.group(4);ch=True;n+=1
if ch: open(p,'w').write('\n'.join(L))
print('fixed',n)
"
```
**b) 局部变量改可空(严格类型,已验证安全)** — 跑完再 `python3 tools/nullfix.py` 吃级联:
```python
python3 -c "
import re,subprocess
ERR=re.compile(r'\s+error\s+-\s+([\w/.\-]+):(\d+):(\d+)\s+-\s+(.*?)\s+-\s+([a-z_]+)\s*\$')
NAMEQ=re.compile(r\"'([^']+)'\"); TYPE=r'(?:[A-Z]\w*(?:<[^;]*>)?|int|double|String|bool|num|dynamic|List<[^;]*>|Map<[^;]*>|Set<[^;]*>)'
out=subprocess.run(['dart','analyze','lib'],capture_output=True,text=True).stdout;tg={}
for ln in out.splitlines():
m=ERR.match(ln)
if m and m.group(5)=='not_assigned_potentially_non_nullable_local_variable':
nm=NAMEQ.search(m.group(4))
if nm: tg.setdefault('lib/'+m.group(1),[]).append((int(m.group(2)),nm.group(1)))
dp=re.compile(r'^(\s+(?:final\s+|const\s+)?)('+TYPE+r')\s+(\w+)\s*;\s*\$');n=0
for p,it in tg.items():
L=open(p).read().split('\n');ch=False;done=set()
for ul,nm in it:
if (ul,nm) in done: continue
done.add((ul,nm))
for i in range(ul-2,-1,-1):
m=dp.match(L[i])
if m and m.group(3)==nm and '?' not in m.group(2): L[i]=m.group(1)+m.group(2)+'? '+nm+';';ch=True;n+=1;break
if ch: open(p,'w').write('\n'.join(L))
print('fixed',n)
"
```
---
## 4. 工具脚本说明(`tools/`)
### `tools/nullfix.py` — 主力自动修复
```bash
python3 tools/nullfix.py # 修整个 lib,默认 5 轮
python3 tools/nullfix.py --max-rounds 12
python3 tools/nullfix.py lib/widgets/mobile/shop.dart # 只修单文件
```
- 每轮重新 `dart analyze lib`,按 error 的 (file,line,col) 精确定位修改。
- **带腐败自检**:每轮后检测 `expected_token`/`missing_identifier`,一旦 >0 立即中止并提示 `git diff`。
- 已实现的 handler:
- `insert_bang`:成员访问/方法调用/迭代器/return 加 `!`(按 analyzer 分类)
- `insert_arg_bang`:`argument_type`/`invalid_assignment` 在参数值末尾加 `!`(值必须是简单标识符链 `[\w.\[\]()!]`,含运算符/空格跳过)
- `late` 实例字段、参数空安全、field-formal 字段空安全
- `missing_default_value_for_parameter`、`@required`→`required` 已并入
- **已禁用的危险 handler**:基于正则的 `if(x)`→`if(x==true)`(曾破坏 89 文件)。条件修复改用 §3.3a 的 analyzer 驱动版。
- **已知边界**:多行表达式(接收者跨行)、含空格/逗号的函数调用参数、三元/比较表达式 → 跳过,需手动。
### `tools/badge_migrate.py` — 未验证,**已不需要**
badges 3.x 迁移已手动完成(`badgeStyle`/`badgeAnimation`),此脚本可忽略/删除。
---
## 5. 延后项
### `lib/utils/util_io.dart`(6 error,仅原生)
- 通过 `dart.library.html` 条件导入从 **Web 构建中排除**,不影响 `flutter build web`。
- 错误来自 `flutter_local_notifications` v17 API 变更:
- `IOSInitializationSettings` / `IOSNotificationDetails` → v17 改名(`DarwinInitializationSettings` / `DarwinNotificationDetails`)
- `onSelectNotification` 参数已移除
- `extra_positional_arguments`(构造参数变化)
- `body_might_complete_normally`(`Future<void>` 缺 return)
- 原生(Android/iOS)构建时才需要修。Web 不阻塞。
---
## 6. 关键上下文 / 决策(避免踩坑)
- **`late` 用于实例字段**:避免模型 `fromJson` 初始化列表 + State 类的级联错误。模型字段置为可空,调用点加 `!`。
- **脚本必须 analyzer 驱动**:盲目正则会损坏代码(如 `return? item;`、`this.?field`)。`nullfix.py` 用 analyzer 的列/列定位 + 腐败自检是关键。
- **badges 实际解析 3.2.0**(不是 2.0.3):参数是 `badgeStyle:`/`badgeAnimation:`(不是 `badgeColor`/`animationType`/`animation`)。
- **pinput 实际 5.0.2**:类名 `Pinput`(非 `PinPut`),导入 `package:pinput/pinput.dart`,`length`/`onCompleted`/`defaultPinDecoration`。
- **youtube_player_iframe 5.2.2**:`YoutubePlayerController.fromVideoId(videoId:, startSeconds:, params:)`。
- **BreadCrumb.route 已改可空**:`String? route`,调用点 `BreadCrumb(X, null)` 合法。
- **e-Transfer**:Stripe 已全移除,付款走 `payment@wisetronic.com`,备注写 `R#<receipt.id>`。
- **搜索框**:自写轻量 `lib/widgets/general/search_bar.dart`(非第三方包)。
- **不升级全局 Flutter SDK**:用本地 Flutter 3.29.3 / Dart 3.7.2。
## 7. 提交历史(基线 f8a90ad 之后)
```
最新 phase3: mobile/shop clean ... 131->118 ← resume 起点
phase3: checkout files clean ... 142->131
phase3: fix attribute widgets ... ~30 fixed
phase3: FIX arg-bang regex (missing \]) ... 235->183 ← 关键 bug 修复
...(共约 28 个 phase3 提交)
f8a90ad 基线
```
## 8. 最终验收
```bash
flutter build web # 目标:无 error,生成 build/web
flutter run -d chrome # 目标:能打开、首页/商品/购物车/结账流程跑通
```
---
## 9. 运行时问题(应用已能运行,以下为后续优化,非阻塞)
应用 `flutter run -d chrome` 已成功启动并加载首页/API 数据/数据库。控制台有以下运行时警告/异常:
### 9.1 Scrollbar 缺 ScrollPosition(真实,影响滚动条显示)
4 个 `Scrollbar(` 未配 `controller`,新版 Flutter 的 Scrollbar 找不到 ScrollPosition:
- `lib/pages/home.dart:101` — ✅ 已修:给 `SingleChildScrollView` 加 `primary: true`
- `lib/pages/blog.dart:24` — 子是 `DesktopBlog`(自定义组件)
- `lib/pages/download.dart:63` — 子是 `DesktopDownloadApps`(自定义组件)
- `lib/widgets/desktop/shop.dart:137` — 包裹 `NotificationListener`
后 3 处的子是自定义组件,需让内部 ListView/ScrollView 暴露 controller(设 `primary: true`)或 Scrollbar 改用 `NotificationListener` 关联。**仅影响滚动条渲染,不影响内容加载/显示。**
### 9.2 CustomersLogo setState-after-dispose(小 bug)
`lib/widgets/desktop/desktop_customers_logo.dart` 的 `Timer.periodic`(每 10s 刷新 logo)未在 `dispose()` 里 `cancel()`,组件卸载后 timer 仍触发 `setState`。建议在 `dispose` 里 `timer?.cancel()`。**热重载时易触发,干净启动偶发。**
### 9.3 `_business` LateInitializationError(热重载假象)
`_business` 是店铺页面组件(`shop_promote.dart`/`shop.dart` 等)的 `late Business` 字段。热重载重建 widget 树时字段状态丢失触发,**干净启动(浏览器刷新 Cmd+R)不会出现**。
> **验证方式**:在浏览器里 Cmd+R 刷新页面(而非热重载),9.2/9.3 类异常应消失,仅剩 9.1 的滚动条警告。
+55
View File
@@ -0,0 +1,55 @@
# flutter_wisetronic 升级日志
## 目标
- 升级到 Dart 3 强制空安全(目标 SDK:本机 Flutter 3.29.3 / Dart 3.7.2,不升级全局)
- 移除 Stripe 收款,改为页面展示 e-transfer email 让客户自行 e-transfer 付款
- 第一阶段:能编译、Web 能跑起来(暂不美化)
## 关键决策
- 目标版本:Flutter 3.29.3 / Dart 3.7.2(钉定本机,不动全局)
- e-transfer 邮箱:`payment@wisetronic.com`
- 提醒客户在 e-transfer remark 里写 `R#<receipt.id>` 以便自动化处理订单
- 搜索框:自写轻量 Web 搜索组件替换 flappy_search_bar
- Dart 3 已移除 `dart migrate`,空安全迁移用手工 + IDE 修复
## 阶段
- [x] 阶段 0:基线 & 锁版本
- [x] 阶段 1:去掉 Stripe
- [x] 阶段 2:依赖替换与升级
- [ ] 阶段 3:空安全迁移
- [ ] 阶段 4:Web 跑起来
---
## 改动记录
### 阶段 0
- 创建 UPGRADE_NOTES.md
- pubspec.yaml: environment sdk `>=2.7.0 <3.0.0` → `>=3.0.0 <4.0.0`,flutter `>=3.29.0`
### 阶段 1 — 去掉 Stripe(已完成)
- 删除: stripe_pay_web.dart, stripe_pay.dart, desktop/mobile_stripe_pay_web.dart, stripe_payment_method.dart
- pubspec: 移除 stripe_payment + stripe_sdk(git)
- user.dart: 移除 stripePaymentMethods 字段与解析
- utils.dart: 移除 createOrUpdateStripePaymentMethod / stripePaymentIntent / stripeChargedSuccess
- util_web.dart / util_io.dart: goPayment 的 stripe/native 分支 → 跳转 ETransferPay
- desktop/mobile_pay_now.dart: 移除“已有卡片”区块与 nativePay 死逻辑,简化列表索引
- desktop/mobile_my_cards.dart: 重写为 e-Transfer 说明页(保留路由入口)
- constants.dart: 新增 ETRANSFER_EMAIL(payment@wisetronic.com) 与 REMARK_PREFIX(R#)
- 新增 lib/widgets/general/e_transfer_pay.dart: 展示邮箱 + 提醒备注写 R#<orderId>
- 保留: PAYMENT_METHOD_CODE_STRIPE='stripe'(API 仍返回该 code,路由到 e-Transfer);payment_platform.dart 的 'stripe' 显示名(后续美化时调整)
### 阶段 2 — 依赖替换与升级(已完成)
**flutter pub get 成功解析 178 个依赖。**
- 升级到 null-safe 最新版:dio ^5.7、cached_network_image ^3.4、url_launcher ^6.3、path_provider ^2.1、image_picker ^1.1、google_maps_flutter ^2.9、geolocator ^12、youtube_player_iframe ^5.2、flutter_local_notifications ^17、uuid ^4、fluttertoast ^8.2、badges ^3、carousel_slider ^5、percent_indicator ^4.2.3、photo_view ^0.15、toggle_switch ^2.3、pinput ^5、email_validator ^3、responsive_builder ^0.7、flutter_redux ^0.10、fluro ^2.0.5、font_awesome_flutter ^10、flutter_spinkit ^5.2、flutter_markdown ^0.7、url_strategy ^0.3、universal_io/html
- 删除(0引用或无 null-safe 版):splashscreen(死代码)、flappy_search_bar、searchable_dropdown、share、platform_detect、flutter_inappwebview、countdown、gender_selection、flutter_dash(死 import)、smooth_star_rating、hovering、ffi
- 新增:flutter_rating_bar ^4.0
- 停维但有 null-safe 版→暂留(Phase 5 再换):pull_to_refresh(→smart_refresher)、hive/hive_flutter(→hive_ce)、catcher ^0.8(→catcher2)
- 新建 null-safe 自定义组件替代废弃包(API 兼容, 调用方仅改 import):
- lib/utils/countdown.dart (CountDown.stream)
- lib/widgets/general/hover_widget.dart (HoverWidget)
- lib/widgets/general/gender_selection.dart (Gender 枚举 + GenderSelection)
- lib/widgets/general/smooth_star_rating.dart (SmoothStarRating)
- lib/widgets/general/search_bar.dart (轻量 Web 搜索 SearchBar + SearchBarController, 含 replayLastSearch 分页)
- main.dart:删除未使用的 _buildBody(SplashScreen) 与 _to 字段
- ⚠️ 待 Phase 3:API 升级破坏性变更(dio5/badges3/toggle_switch2/pinput5/geolocator12 等用法适配) + 整库空安全迁移,按 dart analyze 驱动修复
Executable
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
# Flutter Wisetronic — Web 构建脚本
# 用法:
# ./build_web.sh # 构建 release 版本到 build/web/
# ./build_web.sh run # 构建并在 Chrome 中运行调试版
#
# 说明:
# - 构建(release)必须 --no-tree-shake-icons: 项目中有 24 处 IconData(codePoint)
# 使用来自 JSON/API 的动态 code point(非 const), icon tree-shaking 无法处理。
# 注意: --no-tree-shake-icons 仅 build 支持; flutter run(debug)不做 tree-shaking,
# 因此 run 分支不带该 flag。
# - Dart SDK: 本地 Flutter 3.29.3 / Dart 3.7.2(未升级全局 SDK)。
set -e
cd "$(dirname "$0")"
if [ "$1" = "run" ]; then
echo ">>> flutter run -d chrome"
flutter run -d chrome
else
echo ">>> flutter build web --no-tree-shake-icons"
flutter build web --no-tree-shake-icons
echo ""
echo "✓ 构建完成: build/web/ (main.dart.js: $(du -h build/web/main.dart.js | cut -f1))"
echo " 本地预览: python3 -m http.server --directory build/web 8080"
echo " 然后访问 http://localhost:8080/"
fi
+6 -4
View File
@@ -49,13 +49,15 @@ class Constants {
static const String PAYMENT_METHOD_CODE_OTT_ALIPAY = 'ALIPAY'; static const String PAYMENT_METHOD_CODE_OTT_ALIPAY = 'ALIPAY';
static const String PAYMENT_METHOD_CODE_OTT_WECHATPAY = 'WECHATPAY'; static const String PAYMENT_METHOD_CODE_OTT_WECHATPAY = 'WECHATPAY';
static const String PAYMENT_METHOD_CODE_PAYPAL = 'paypal'; static const String PAYMENT_METHOD_CODE_PAYPAL = 'paypal';
static const String PAYMENT_METHOD_CODE_STRIPE = 'stripe'; static const String PAYMENT_METHOD_CODE_STRIPE = 'stripe'; // API still returns 'stripe' code; now routed to e-Transfer
static const String PAYMENT_METHOD_CODE_POD = 'payondeliverypickup'; static const String PAYMENT_METHOD_CODE_POD = 'payondeliverypickup';
static const String PAYMENT_METHOD_NATIVE_PAY = 'native_pay'; static const String PAYMENT_METHOD_NATIVE_PAY = 'native_pay';
static const String STRIPE_STATUS_REQUIRES_CONFIRMATION = 'requires_confirmation'; // e-Transfer (replaces Stripe)
static const String STRIPE_CLIENT_SECRET = 'client_secret'; static const String ETRANSFER_EMAIL = 'payment@wisetronic.com';
static const String STRIPE_STATUS_SUCCEDED = 'succeeded'; static const String ETRANSFER_QA = 'wisetronic'; // security question answer placeholder, if needed
// Remark template for auto-processing: R#<receipt id> (= order id)
static const String ETRANSFER_REMARK_PREFIX = 'R#';
static const int STATUS_PENDING = 0; static const int STATUS_PENDING = 0;
static const int STATUS_ACCEPT = 1; static const int STATUS_ACCEPT = 1;
+1 -1
View File
@@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
import 'package:photo_view/photo_view.dart'; import 'package:photo_view/photo_view.dart';
class ImageViewer extends StatefulWidget { class ImageViewer extends StatefulWidget {
final Key key; final Key? key;
final ImageProvider imageProvider; final ImageProvider imageProvider;
ImageViewer(this.imageProvider, {this.key}) : ImageViewer(this.imageProvider, {this.key}) :
+1 -1
View File
@@ -87,7 +87,7 @@ class OnProductWillAddToCart {
double price; double price;
String description; String description;
Business business; Business business;
GlobalKey buttonKey; GlobalKey? buttonKey;
OnProductWillAddToCart(this.product, this.selections, this.price, this.description, this.business, {this.buttonKey}); OnProductWillAddToCart(this.product, this.selections, this.price, this.description, this.business, {this.buttonKey});
} }
+2 -2
View File
@@ -24,7 +24,7 @@ Map<String, LibraryLoader> _deferredLibraries = {
'zh_CN': () => new Future.value(null), 'zh_CN': () => new Future.value(null),
}; };
MessageLookupByLibrary _findExact(String localeName) { MessageLookupByLibrary? _findExact(String localeName) {
switch (localeName) { switch (localeName) {
case 'en': case 'en':
return messages_en.messages; return messages_en.messages;
@@ -59,7 +59,7 @@ bool _messagesExistFor(String locale) {
} }
} }
MessageLookupByLibrary _findGeneratedMessagesFor(String locale) { MessageLookupByLibrary? _findGeneratedMessagesFor(String locale) {
var actualLocale = Intl.verifiedLocale(locale, _messagesExistFor, var actualLocale = Intl.verifiedLocale(locale, _messagesExistFor,
onFailure: (_) => null); onFailure: (_) => null);
if (actualLocale == null) return null; if (actualLocale == null) return null;
+2 -2
View File
@@ -15,7 +15,7 @@ import 'intl/messages_all.dart';
class S { class S {
S(); S();
static S current; static S current = S();
static const AppLocalizationDelegate delegate = static const AppLocalizationDelegate delegate =
AppLocalizationDelegate(); AppLocalizationDelegate();
@@ -32,7 +32,7 @@ class S {
} }
static S of(BuildContext context) { static S of(BuildContext context) {
return Localizations.of<S>(context, S); return Localizations.of<S>(context, S) ?? S.current;
} }
/// `About` /// `About`
+16 -26
View File
@@ -14,7 +14,6 @@ import 'pages/create_online_store_1.dart';
import 'pages/download.dart'; import 'pages/download.dart';
import 'pages/me.dart'; import 'pages/me.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:splashscreen/splashscreen.dart';
// import 'package:uni_links/uni_links.dart'; // import 'package:uni_links/uni_links.dart';
import 'constants.dart'; import 'constants.dart';
@@ -34,15 +33,20 @@ import 'utils/utils.dart';
void main() { void main() {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
FlutterError.onError = (details) {
FlutterError.presentError(details);
print('CK_ERROR: ${details.exceptionAsString()}');
print('CK_CTX: ${details.context}');
print('CK_STACK: ${details.stack}');
};
// Enable configureApp will cause route problem. // Enable configureApp will cause route problem.
// configureApp(); // configureApp();
setPathUrlStrategy(); setPathUrlStrategy();
runApp(MyApp()); runApp(MyApp());
Future.delayed(Duration(seconds: 3), () => Util.devAutologin()); // DEV e2e: 延迟 3s 等 Flutter/Hive ready
} }
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget {
String _to = '/';
MyApp() { MyApp() {
Routes.configure(); Routes.configure();
Utils().init(); Utils().init();
@@ -95,24 +99,6 @@ class MyApp extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Widget _buildBody() {
return SplashScreen(
seconds: 5,
routeName: _to,
navigateAfterSeconds: Home(title: Constants.APP_TITLE,),
styleTextUnderTheLoader: new TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20.0,
),
imageBackground: (Image.network(Constants.BASE_API_URL + 'gallery/get-minimanager-splash/')).image,
backgroundColor: Colors.white,
onClick: () {
},
loaderColor: Colors.blue,
);
}
return MaterialApp( return MaterialApp(
debugShowCheckedModeBanner: Constants.DEBUG, debugShowCheckedModeBanner: Constants.DEBUG,
navigatorKey: kIsWeb ? null : Catcher.navigatorKey, navigatorKey: kIsWeb ? null : Catcher.navigatorKey,
@@ -124,7 +110,11 @@ class MyApp extends StatelessWidget {
S.delegate, S.delegate,
], ],
supportedLocales: S.delegate.supportedLocales, supportedLocales: S.delegate.supportedLocales,
localeResolutionCallback: (Locale locale, Iterable<Locale> supportedLocales) { localeResolutionCallback: (Locale? locale, Iterable<Locale> supportedLocales) {
if (locale == null) {
store.dispatch(UpdateLocale(supportedLocales.first));
return supportedLocales.first;
}
print('Language code: ${locale.languageCode}, Country code: ${locale.countryCode}'); print('Language code: ${locale.languageCode}, Country code: ${locale.countryCode}');
for (final supportedLocale in supportedLocales) { for (final supportedLocale in supportedLocales) {
if (supportedLocale.languageCode == locale.languageCode) { if (supportedLocale.languageCode == locale.languageCode) {
@@ -136,9 +126,9 @@ class MyApp extends StatelessWidget {
return supportedLocales.first; return supportedLocales.first;
}, },
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
final List<String> pathElements = settings.name.split('/'); final List<String> pathElements = settings.name?.split('/') ?? [];
print('path elements: $pathElements'); print('path elements: $pathElements');
if (pathElements[0] != '') { if (pathElements.isEmpty || pathElements[0] != '') {
return null; return null;
} }
if (pathElements[1] == 'me') { if (pathElements[1] == 'me') {
@@ -182,12 +172,12 @@ class MyApp extends StatelessWidget {
), ),
); );
} }
if (pathElements[1] == 'renew-minioffice') { if (pathElements[1] == 'renew-minioffice' && pathElements.length >= 3) {
return MaterialPageRoute(builder: (BuildContext context) => return MaterialPageRoute(builder: (BuildContext context) =>
RenewMiniOffice(int.parse(pathElements[2])) RenewMiniOffice(int.parse(pathElements[2]))
); );
} }
if (pathElements[1] == 'buy-service') { if (pathElements[1] == 'buy-service' && pathElements.length >= 4) {
return MaterialPageRoute(builder: (BuildContext context) => return MaterialPageRoute(builder: (BuildContext context) =>
BuyService(int.parse(pathElements[2]), pathElements[3]) BuyService(int.parse(pathElements[2]), pathElements[3])
); );
+12 -12
View File
@@ -4,9 +4,9 @@ import 'dart:convert';
import 'package:flutter_wisetronic/models/product_attribute.dart'; import 'package:flutter_wisetronic/models/product_attribute.dart';
class Subproduct { class Subproduct {
int id; int? id;
SimpleProduct product; SimpleProduct? product;
double quantity; double? quantity;
Subproduct.fromJson(Map<String, dynamic> json) : Subproduct.fromJson(Map<String, dynamic> json) :
id = json['id'], id = json['id'],
@@ -26,15 +26,15 @@ class Subproduct {
} }
class SimpleProduct { class SimpleProduct {
int id; int? id;
String name; String? name;
String sku; String? sku;
double price; double? price;
String description; String? description;
String image; String? image;
List<ProductAttribute> productAttributes; List<ProductAttribute>? productAttributes;
double customerLastPrice; double? customerLastPrice;
String extraData; String? extraData;
SimpleProduct.fromJson(Map<String, dynamic> json) : SimpleProduct.fromJson(Map<String, dynamic> json) :
id = json['id'], id = json['id'],
+15 -15
View File
@@ -1,21 +1,21 @@
import 'dart:convert'; import 'dart:convert';
class Address { class Address {
int id; int? id;
String addressLine1; String? addressLine1;
String addressLine2; String? addressLine2;
String city; String? city;
String state; String? state;
String country; String? country;
String zip; String? zip;
String phone; String? phone;
String fax; String? fax;
String email; String? email;
String contactName; String? contactName;
int gender; int? gender;
String lat; String? lat;
String lng; String? lng;
String fullAddress; String? fullAddress;
Address.fromJson(Map<String, dynamic> json) Address.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
+10 -10
View File
@@ -2,8 +2,8 @@
import 'dart:convert'; import 'dart:convert';
class Section { class Section {
int id; int? id;
String name; String? name;
Section.fromJson(Map<String, dynamic> json) : Section.fromJson(Map<String, dynamic> json) :
id = json['id'], id = json['id'],
@@ -21,14 +21,14 @@ class Section {
} }
class Blog { class Blog {
int id; int? id;
String title; String? title;
String body; String? body;
String createdAt; String? createdAt;
String thumbUrl; String? thumbUrl;
String imageUrl; String? imageUrl;
String videoUrl; String? videoUrl;
Section section; Section? section;
Blog.fromJson(Map<String, dynamic> json) : Blog.fromJson(Map<String, dynamic> json) :
id = json['id'], id = json['id'],
+4 -4
View File
@@ -4,10 +4,10 @@ import 'dart:convert';
import 'booking_time.dart'; import 'booking_time.dart';
class BookingDateTime { class BookingDateTime {
String viewDate; String? viewDate;
int unixTime; int? unixTime;
String sendTimeTip; String? sendTimeTip;
List<BookingTime> bookTimes; List<BookingTime>? bookTimes;
BookingDateTime(this.viewDate, this.unixTime, this.sendTimeTip, this.bookTimes); BookingDateTime(this.viewDate, this.unixTime, this.sendTimeTip, this.bookTimes);
+3 -3
View File
@@ -2,9 +2,9 @@
import 'dart:convert'; import 'dart:convert';
class BookingTime { class BookingTime {
String viewTime; String? viewTime;
int unixTime; int? unixTime;
String sendTimeTip; String? sendTimeTip;
BookingTime(this.viewTime, this.unixTime, this.sendTimeTip); BookingTime(this.viewTime, this.unixTime, this.sendTimeTip);
+43 -43
View File
@@ -8,7 +8,7 @@ import 'product.dart';
import 'waiting_line.dart'; import 'waiting_line.dart';
class QuickInput { class QuickInput {
String value; String? value;
QuickInput.fromJson(Map<String, dynamic> json) QuickInput.fromJson(Map<String, dynamic> json)
: value = json['value']; : value = json['value'];
@@ -23,48 +23,48 @@ class QuickInput {
} }
class Business { class Business {
int id; int? id;
String name; String? name;
String phone; String? phone;
Address address; Address? address;
String fullAddress; String? fullAddress;
String picUrl; String? picUrl;
int status; int? status;
List<BusinessTime> openingTime; List<BusinessTime>? openingTime;
double shippingFee; double? shippingFee;
double packageFee; double? packageFee;
double minPrice; double? minPrice;
int shippingTime; int? shippingTime;
int monthSales; int? monthSales;
String bulletin; String? bulletin;
int category; int? category;
bool isLike; bool? isLike;
String description; String? description;
String policy; String? policy;
String bannerImageUrl; String? bannerImageUrl;
int todayOpen; int? todayOpen;
int todayClose; int? todayClose;
bool showMonthlySold; bool? showMonthlySold;
List<ImageUrl> slideImages; List<ImageUrl>? slideImages;
List<Product> promoProducts; List<Product>? promoProducts;
String paypalEmail; String? paypalEmail;
bool deliveryCanadaPost; bool? deliveryCanadaPost;
bool deliveryStoreDelivery; bool? deliveryStoreDelivery;
bool deliveryPickup; bool? deliveryPickup;
String currency; String? currency;
List<WaitingLine> waitingLine; List<WaitingLine>? waitingLine;
bool enableWaitingLine; bool? enableWaitingLine;
double pointsToCreditsConversionRate; double? pointsToCreditsConversionRate;
String chaseXLogin; String? chaseXLogin;
String chaseTransactionKey; String? chaseTransactionKey;
String chaseResponseKey; String? chaseResponseKey;
DistanceInfo distanceInfo; DistanceInfo? distanceInfo;
int commentsCount; int? commentsCount;
bool forceClose; bool? forceClose;
bool isPublic; bool? isPublic;
double referrerCoupon; double? referrerCoupon;
bool instanceDelivery; bool? instanceDelivery;
List<QuickInput> quickInputs; List<QuickInput>? quickInputs;
Business.fromJson(Map<String, dynamic> json) Business.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
+2 -2
View File
@@ -1,8 +1,8 @@
import 'dart:convert'; import 'dart:convert';
class BusinessTime { class BusinessTime {
String openTime; String? openTime;
String closeTime; String? closeTime;
BusinessTime.fromJson(Map<String, dynamic> json) BusinessTime.fromJson(Map<String, dynamic> json)
: openTime = json['open_time'], : openTime = json['open_time'],
+19 -19
View File
@@ -7,18 +7,18 @@ import 'cart_line_item.dart';
import 'extra_fee.dart'; import 'extra_fee.dart';
class CartInfo { class CartInfo {
int id; int? id;
double originPrice; double? originPrice;
double discountPrice; double? discountPrice;
double totalPrice; double? totalPrice;
Business businessInfo; Business? businessInfo;
List<CartLineItem> productList; List<CartLineItem>? productList;
List<ExtraFee> extraFeeList; List<ExtraFee>? extraFeeList;
List<ExtraFee> discountList; List<ExtraFee>? discountList;
int deliveryMethod; int? deliveryMethod;
String shippingMethod; String? shippingMethod;
double amountPaid; double? amountPaid;
String extraData; String? extraData;
CartInfo.fromJson(Map<String, dynamic> json) CartInfo.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
@@ -53,7 +53,7 @@ class CartInfo {
if (productList == null) { if (productList == null) {
productList = [item]; productList = [item];
} else { } else {
productList.add(item); productList!.add(item);
} }
} }
@@ -74,19 +74,19 @@ class CartInfo {
originPrice = 0.0; originPrice = 0.0;
discountPrice = 0.0; discountPrice = 0.0;
totalPrice = 0.0; totalPrice = 0.0;
for (var i = 0; i < productList.length; i++) { for (var i = 0; i < (productList?.length ?? 0); i++) {
newTotal += productList[i].getTotalPrice(); newTotal += productList![i].getTotalPrice();
} }
originPrice = newTotal; originPrice = newTotal;
totalPrice = newTotal; totalPrice = newTotal;
return totalPrice; return totalPrice ?? 0.0;
} }
int getProductListTotalQuantity() { int getProductListTotalQuantity() {
int qty = 0; int qty = 0;
if (productList != null && productList.length > 0) { if (productList != null && productList!.length > 0) {
for (var i = 0; i < productList.length; i++) { for (var i = 0; i < productList!.length; i++) {
qty += productList[i].quantity.round(); qty += (productList![i].quantity ?? 0).round();
} }
} }
return qty; return qty;
+11 -11
View File
@@ -6,15 +6,15 @@ import 'package:uuid/uuid.dart';
import 'product.dart'; import 'product.dart';
class CartLineItem { class CartLineItem {
int id; int? id;
double unitPrice; double? unitPrice;
double totalPrice; double? totalPrice;
Product product; Product? product;
String name; String? name;
String description; String? description;
double quantity; double? quantity;
String uuid; String? uuid;
String parentUuid; String? parentUuid;
CartLineItem() { CartLineItem() {
uuid = Uuid().v4(); uuid = Uuid().v4();
@@ -48,7 +48,7 @@ class CartLineItem {
} }
double getTotalPrice() { double getTotalPrice() {
totalPrice = unitPrice * quantity; totalPrice = (unitPrice ?? 0.0) * (quantity ?? 0);
return totalPrice; return totalPrice ?? 0.0;
} }
} }
+2 -2
View File
@@ -2,8 +2,8 @@
import 'dart:convert'; import 'dart:convert';
class Category { class Category {
int id; int? id;
String name; String? name;
Category.fromJson(Map<String, dynamic> json) Category.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
+6 -6
View File
@@ -4,12 +4,12 @@ import 'dart:convert';
import 'product.dart'; import 'product.dart';
class CategoryProducts { class CategoryProducts {
int id; int? id;
int businessId; int? businessId;
String name; String? name;
String description; String? description;
String iconUrl; String? iconUrl;
List<Product> products; List<Product>? products;
CategoryProducts.fromJson(Map<String, dynamic> json) CategoryProducts.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
+9 -9
View File
@@ -4,15 +4,15 @@ import 'dart:convert';
import 'product_image.dart'; import 'product_image.dart';
class Comment { class Comment {
int id; int? id;
String contact; String? contact;
String content; String? content;
int rating; int? rating;
List<ProductImage> images; List<ProductImage>? images;
String createdAt; String? createdAt;
int thumbUp; int? thumbUp;
int thumbDown; int? thumbDown;
String replyFromStore; String? replyFromStore;
Comment.fromJson(Map<String, dynamic> json) : Comment.fromJson(Map<String, dynamic> json) :
id = json['id'], id = json['id'],
+8 -8
View File
@@ -4,14 +4,14 @@ import 'dart:convert';
import 'business.dart'; import 'business.dart';
class Coupon { class Coupon {
int id; int? id;
String code; String? code;
String description; String? description;
String expirationDate; String? expirationDate;
double minAmount; double? minAmount;
Business store; Business? store;
double valueAmount; double? valueAmount;
bool isPercentage; bool? isPercentage;
Coupon.fromJson(Map<String, dynamic> json) Coupon.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
+3 -3
View File
@@ -4,9 +4,9 @@ import 'dart:convert';
import 'text_value.dart'; import 'text_value.dart';
class DistanceInfo { class DistanceInfo {
TextValue duration; TextValue? duration;
TextValue distance; TextValue? distance;
String status; String? status;
DistanceInfo.fromJson(Map<String, dynamic> json) DistanceInfo.fromJson(Map<String, dynamic> json)
: duration = json['duration'] != null ? TextValue.fromJson(json['duration']) : null, : duration = json['duration'] != null ? TextValue.fromJson(json['duration']) : null,
+2 -2
View File
@@ -2,8 +2,8 @@
import 'dart:convert'; import 'dart:convert';
class ErrorMessage { class ErrorMessage {
String code; String? code;
String string; String? string;
ErrorMessage.fromJson(Map<String, dynamic> json) ErrorMessage.fromJson(Map<String, dynamic> json)
: code = json['code'], : code = json['code'],
+5 -5
View File
@@ -3,11 +3,11 @@
import 'dart:convert'; import 'dart:convert';
class ExtraFee { class ExtraFee {
int id; int? id;
String name; String? name;
String description; String? description;
double rate; double? rate;
double price; double? price;
ExtraFee.fromJson(Map<String, dynamic> json) ExtraFee.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
+5 -5
View File
@@ -2,11 +2,11 @@
import 'dart:convert'; import 'dart:convert';
class Fulfillment { class Fulfillment {
int id; int? id;
String shippingMethod; String? shippingMethod;
String trackingNumber; String? trackingNumber;
String note; String? note;
String createdAt; String? createdAt;
Fulfillment.fromJson(Map<String, dynamic> json) : Fulfillment.fromJson(Map<String, dynamic> json) :
id = json['id'], id = json['id'],
+3 -3
View File
@@ -2,9 +2,9 @@
import 'dart:convert'; import 'dart:convert';
class Gallery { class Gallery {
int id; int? id;
String image; String? image;
String linkUrl; String? linkUrl;
Gallery.fromJson(Map<String, dynamic> json) Gallery.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
+2 -2
View File
@@ -3,8 +3,8 @@
import 'dart:convert'; import 'dart:convert';
class Group { class Group {
int id; int? id;
String name; String? name;
Group.fromJson(Map<String, dynamic> json) : Group.fromJson(Map<String, dynamic> json) :
id = json['id'], id = json['id'],
+2 -2
View File
@@ -1,8 +1,8 @@
import 'dart:convert'; import 'dart:convert';
class ImageUrl { class ImageUrl {
int id; int? id;
String imageUrl; String? imageUrl;
ImageUrl.fromJson(Map<String, dynamic> json) ImageUrl.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
+2 -2
View File
@@ -1,7 +1,7 @@
class KeyValue { class KeyValue {
String name; String? name;
dynamic value; dynamic? value;
KeyValue(this.name, this.value); KeyValue(this.name, this.value);
+11 -11
View File
@@ -1,17 +1,17 @@
import 'dart:convert'; import 'dart:convert';
class LocatedAddress { class LocatedAddress {
int storeId; int? storeId;
double latitude; double? latitude;
double longitude; double? longitude;
String streetNumber; String? streetNumber;
String streetName; String? streetName;
String city; String? city;
String locality; String? locality;
String province; String? province;
String country; String? country;
String postalCode; String? postalCode;
String formattedAddress; String? formattedAddress;
LocatedAddress.fromJson(Map<String, dynamic> json) LocatedAddress.fromJson(Map<String, dynamic> json)
: storeId = json['store_id'], : storeId = json['store_id'],
+27 -27
View File
@@ -11,33 +11,33 @@ import 'fulfillment.dart';
import 'user_position.dart'; import 'user_position.dart';
class Order { class Order {
int id; int? id;
int userId; int? userId;
int businessId; int? businessId;
Business businessInfo; Business? businessInfo;
CartInfo cartInfo; CartInfo? cartInfo;
int status; int? status;
double originPrice; double? originPrice;
double discountPrice; double? discountPrice;
double totalPrice; double? totalPrice;
String consignee; String? consignee;
String phone; String? phone;
String address; String? address;
Address shippingAddress; Address? shippingAddress;
int payMethod; int? payMethod;
String remark; String? remark;
String orderNum; String? orderNum;
int bookedAt; int? bookedAt;
int createdAt; int? createdAt;
String shippingMethod; String? shippingMethod;
String paymentStatus; // UNPAID, PAID, PARTIALPAID String paymentStatus; // UNPAID, PAID, PARTIALPAID
double amountPaid; double? amountPaid;
List<Fulfillment> fulfillments; List<Fulfillment>? fulfillments;
String extraData; String? extraData;
bool hasComment; bool? hasComment;
double fee; double? fee;
UserPosition shipperPosition; UserPosition? shipperPosition;
DistanceInfo deliveryDistance; DistanceInfo? deliveryDistance;
Order.fromJson(Map<String, dynamic> json) Order.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
@@ -100,7 +100,7 @@ class Order {
double getSubtotal() { double getSubtotal() {
double subtotal = 0.0; double subtotal = 0.0;
for (CartLineItem lineItem in cartInfo.productList) { for (CartLineItem lineItem in cartInfo?.productList ?? <CartLineItem>[]) {
subtotal += lineItem.getTotalPrice(); subtotal += lineItem.getTotalPrice();
} }
return subtotal; return subtotal;
+13 -13
View File
@@ -6,19 +6,19 @@ import 'package:flutter/cupertino.dart';
import '../generated/l10n.dart'; import '../generated/l10n.dart';
class PaymentPlatform { class PaymentPlatform {
int id; int? id;
String name; String? name;
String code; String? code;
String method; String? method;
String icon; String? icon;
String xLogin; String? xLogin;
String transactionKey; String? transactionKey;
String responseKey; String? responseKey;
String squareAppId; String? squareAppId;
String squareAccessToken; String? squareAccessToken;
String squareLocationId; String? squareLocationId;
String publishableKey; String? publishableKey;
String merchantId; String? merchantId;
PaymentPlatform(this.code); PaymentPlatform(this.code);
+2 -2
View File
@@ -1,7 +1,7 @@
class Position { class Position {
final double latitude; final double? latitude;
final double longitude; final double? longitude;
Position({this.latitude, this.longitude}); Position({this.latitude, this.longitude});
+17 -17
View File
@@ -5,23 +5,23 @@ import 'Subproduct.dart';
import 'product_attribute.dart'; import 'product_attribute.dart';
class Product { class Product {
int id; int? id;
int businessId; int? businessId;
int categoryId; int? categoryId;
String name; String? name;
double price; double? price;
double regularPrice; double? regularPrice;
String description; String? description;
String detailDescription; String? detailDescription;
String imagePath; String? imagePath;
String secondImagePath; String? secondImagePath;
double monthSales; double? monthSales;
int rate; int? rate;
double leftNum; double? leftNum;
List<ProductAttribute> productAttributes; List<ProductAttribute>? productAttributes;
bool nonInventory; bool? nonInventory;
String extraData; String? extraData;
List<Subproduct> subproducts; List<Subproduct>? subproducts;
Product(int id, int businessId, String name, double price, String description, Product(int id, int businessId, String name, double price, String description,
String imagePath, List<ProductAttribute> productAttributes) { String imagePath, List<ProductAttribute> productAttributes) {
+8 -8
View File
@@ -4,14 +4,14 @@ import 'dart:convert';
import 'product_option.dart'; import 'product_option.dart';
class ProductAttribute { class ProductAttribute {
int id; int? id;
String name; String? name;
List<ProductOption> productOptions; List<ProductOption>? productOptions;
bool singleSelection; bool? singleSelection;
bool byQuantity; bool? byQuantity;
bool required; bool? required;
String extra; String? extra;
bool disabled; bool? disabled;
ProductAttribute.fromJson(Map<String, dynamic> json) ProductAttribute.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
+24 -24
View File
@@ -8,30 +8,30 @@ import 'product_attribute.dart';
import 'product_image.dart'; import 'product_image.dart';
class ProductDetail { class ProductDetail {
int id; int? id;
String image; String? image;
List<ProductImage> images; List<ProductImage>? images;
String sku; String? sku;
String name; String? name;
double price; double? price;
double regularPrice; double? regularPrice;
String description; String? description;
String description2; String? description2;
String detailDescription; String? detailDescription;
double monthSales; double? monthSales;
int rate; int? rate;
double leftNum; double? leftNum;
List<ProductAttribute> productAttributes; List<ProductAttribute>? productAttributes;
bool nonInventory; bool? nonInventory;
String extraData; String? extraData;
String purchaseNote; String? purchaseNote;
double weight; double? weight;
double dimentionsLength; double? dimentionsLength;
double dimentionsWidth; double? dimentionsWidth;
double dimentionsHeight; double? dimentionsHeight;
bool reviewsAllowed; bool? reviewsAllowed;
List<Category> categories; List<Category>? categories;
List<Subproduct> subproducts; List<Subproduct>? subproducts;
ProductDetail.fromJson(Map<String, dynamic> json) ProductDetail.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
+2 -2
View File
@@ -1,8 +1,8 @@
import 'dart:convert'; import 'dart:convert';
class ProductImage { class ProductImage {
int id; int? id;
String image; String? image;
ProductImage.fromJson(Map<String, dynamic> json) ProductImage.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
+5 -5
View File
@@ -2,11 +2,11 @@
import 'dart:convert'; import 'dart:convert';
class ProductOption { class ProductOption {
int id; int? id;
String name; String? name;
double adjustAmount; double? adjustAmount;
String extra; String? extra;
bool disabled; bool? disabled;
ProductOption.fromJson(Map<String, dynamic> json) ProductOption.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
+7 -7
View File
@@ -4,9 +4,9 @@ import 'dart:convert';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
class ShippingRate { class ShippingRate {
String name; String? name;
double price; double? price;
List<Rate> rates; List<Rate>? rates;
ShippingRate.fromJson(Map<String, dynamic> json) ShippingRate.fromJson(Map<String, dynamic> json)
: name = json['name'], : name = json['name'],
@@ -25,7 +25,7 @@ class ShippingRate {
other is ShippingRate && other is ShippingRate &&
runtimeType == other.runtimeType && runtimeType == other.runtimeType &&
name == other.name && name == other.name &&
price.toStringAsFixed(2) == other.price.toStringAsFixed(2) && price?.toStringAsFixed(2) == other.price?.toStringAsFixed(2) &&
listEquals(rates, other.rates); listEquals(rates, other.rates);
@override @override
@@ -41,8 +41,8 @@ class ShippingRate {
} }
class Rate { class Rate {
String name; String? name;
double rate; double? rate;
Rate.fromJson(Map<String, dynamic> json) Rate.fromJson(Map<String, dynamic> json)
: name = json['name'], : name = json['name'],
@@ -59,7 +59,7 @@ class Rate {
other is Rate && other is Rate &&
runtimeType == other.runtimeType && runtimeType == other.runtimeType &&
name == other.name && name == other.name &&
rate.toStringAsFixed(2) == other.rate.toStringAsFixed(2); rate?.toStringAsFixed(2) == other.rate?.toStringAsFixed(2);
@override @override
String toString() { String toString() {
+3 -3
View File
@@ -4,9 +4,9 @@ import 'dart:convert';
import 'address.dart'; import 'address.dart';
class Store { class Store {
int id; int? id;
String name; String? name;
Address address; Address? address;
Store.fromJson(Map<String, dynamic> json) Store.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
+6 -6
View File
@@ -1,12 +1,12 @@
import 'dart:convert'; import 'dart:convert';
class SimpleProduct { class SimpleProduct {
int id; int? id;
String name; String? name;
double price; double? price;
double regularPrice; double? regularPrice;
String description; String? description;
String imagePath; String? imagePath;
SimpleProduct.fromJson(Map<String, dynamic> json) SimpleProduct.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
-46
View File
@@ -1,46 +0,0 @@
import 'dart:convert';
class StripePaymentMethod {
int id;
String customerId;
String paymentMethodId;
String paymentMethodType;
String cardBrand;
String cardCountry;
int cardExpMonth;
int cardExpYear;
String cardFunding;
String cardLast4;
StripePaymentMethod.fromJson(Map<String, dynamic> json) :
id = json['id'],
customerId = json['customer_id'],
paymentMethodId = json['payment_method_id'],
paymentMethodType = json['payment_method_type'],
cardBrand = json['card_brand'],
cardCountry = json['card_country'],
cardExpMonth = json['card_exp_month'],
cardExpYear = json['card_exp_year'],
cardFunding = json['card_funding'],
cardLast4 = json['card_last4'];
Map<String, dynamic> toJson() => {
'id': id,
'customer_id': customerId,
'payment_method_id': paymentMethodId,
'payment_method_type': paymentMethodType,
'card_brand': cardBrand,
'card_country': cardCountry,
'card_exp_month': cardExpMonth,
'card_exp_year': cardExpYear,
'card_funding': cardFunding,
'card_last4': cardLast4,
};
@override
String toString() {
return json.encode(this);
}
}
+2 -2
View File
@@ -2,8 +2,8 @@
import 'dart:convert'; import 'dart:convert';
class TextValue { class TextValue {
String text; String? text;
int value; int? value;
TextValue.fromJson(Map<String, dynamic> json) TextValue.fromJson(Map<String, dynamic> json)
: text = json['text'], : text = json['text'],
+18 -18
View File
@@ -4,10 +4,10 @@ import 'dart:convert';
import 'simple_business.dart'; import 'simple_business.dart';
class TicketFile { class TicketFile {
int id; int? id;
String url; String? url;
String fileName; String? fileName;
String fileType; String? fileType;
TicketFile.fromJson(Map<String, dynamic> json) TicketFile.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
@@ -29,9 +29,9 @@ class TicketFile {
} }
class Issue { class Issue {
int id; int? id;
String msg; String? msg;
List<TicketFile> files; List<TicketFile>? files;
Issue.fromJson(Map<String, dynamic> json) Issue.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
@@ -51,11 +51,11 @@ class Issue {
} }
class FollowUp { class FollowUp {
int id; int? id;
String msg; String? msg;
String poster; String? poster;
String createdAt; String? createdAt;
List<TicketFile> files; List<TicketFile>? files;
FollowUp.fromJson(Map<String, dynamic> json) FollowUp.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
@@ -79,12 +79,12 @@ class FollowUp {
} }
class Ticket { class Ticket {
int id; int? id;
Issue issue; Issue? issue;
Store store; Store? store;
List<FollowUp> followUps; List<FollowUp>? followUps;
bool isClosed; bool? isClosed;
String createdAt; String? createdAt;
Ticket.fromJson(Map<String, dynamic> json) Ticket.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
+17 -22
View File
@@ -1,26 +1,23 @@
import 'dart:convert'; import 'dart:convert';
import 'stripe_payment_method.dart';
class User { class User {
int id; int? id;
String username; String? username;
String nickname; String? nickname;
String mobile; String? mobile;
String email; String? email;
String avatarUrl; String? avatarUrl;
int lastAddressId; int? lastAddressId;
String passCode; String? passCode;
double credit; double? credit;
double wallet; double? wallet;
int coupon; int? coupon;
int points; int? points;
int orderNum; int? orderNum;
double pointsToCreditsConversionRate; double? pointsToCreditsConversionRate;
String contactNumber; String? contactNumber;
String flutterMiniStoreToken; String? flutterMiniStoreToken;
List<StripePaymentMethod> stripePaymentMethods;
User.fromJson(Map<String, dynamic> json) User.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
@@ -38,8 +35,7 @@ class User {
orderNum = json['order_num'], orderNum = json['order_num'],
pointsToCreditsConversionRate = double.parse(json['points_to_credits_conversion_rate'].toString()), pointsToCreditsConversionRate = double.parse(json['points_to_credits_conversion_rate'].toString()),
contactNumber = json['contact_number'], contactNumber = json['contact_number'],
flutterMiniStoreToken = json['flutter_ministore_token'], flutterMiniStoreToken = json['flutter_ministore_token'];
stripePaymentMethods = (json['stripe_payment_methods'] as List).map((e) => StripePaymentMethod.fromJson(e)).toList();
Map<String, dynamic> toJson() => { Map<String, dynamic> toJson() => {
'id': id, 'id': id,
@@ -58,7 +54,6 @@ class User {
'points_to_credits_conversion_rate': pointsToCreditsConversionRate, 'points_to_credits_conversion_rate': pointsToCreditsConversionRate,
'contact_number': contactNumber, 'contact_number': contactNumber,
'flutter_ministore_token': flutterMiniStoreToken, 'flutter_ministore_token': flutterMiniStoreToken,
'stripe_payment_methods': stripePaymentMethods,
}; };
@override @override
+2 -2
View File
@@ -2,8 +2,8 @@
import 'dart:convert'; import 'dart:convert';
class UserPosition { class UserPosition {
double lat; double? lat;
double lng; double? lng;
UserPosition.fromJson(Map<String, dynamic> json) : UserPosition.fromJson(Map<String, dynamic> json) :
lat = double.parse(json['lat'].toString()), lat = double.parse(json['lat'].toString()),
+2 -2
View File
@@ -4,8 +4,8 @@ import 'dart:convert';
import 'waiting_line_item.dart'; import 'waiting_line_item.dart';
class WaitingLine { class WaitingLine {
List<WaitingLineItem> waitingLines; List<WaitingLineItem>? waitingLines;
String storeSn; String? storeSn;
WaitingLine.fromJson(Map<String, dynamic> json) WaitingLine.fromJson(Map<String, dynamic> json)
: waitingLines = (json['waiting_lines'] as List).map((i) => WaitingLineItem.fromJson(i)).toList(), : waitingLines = (json['waiting_lines'] as List).map((i) => WaitingLineItem.fromJson(i)).toList(),
+5 -5
View File
@@ -1,11 +1,11 @@
import 'dart:convert'; import 'dart:convert';
class WaitingLineItem { class WaitingLineItem {
String deviceId; String? deviceId;
String phone; String? phone;
String createdAt; String? createdAt;
int peopleCount; int? peopleCount;
int waitingNumber; int? waitingNumber;
WaitingLineItem.fromJson(Map<String, dynamic> json) WaitingLineItem.fromJson(Map<String, dynamic> json)
: deviceId = json['device_id'], : deviceId = json['device_id'],
+7 -7
View File
@@ -6,20 +6,20 @@ import '../models/business.dart';
import '../models/product.dart'; import '../models/product.dart';
class AttributeSelection extends StatelessWidget { class AttributeSelection extends StatelessWidget {
final Product product; final Product? product;
final Business business; final Business? business;
final GlobalKey startKey; final GlobalKey? startKey;
const AttributeSelection({Key key, this.product, this.business, this.startKey}) : super(key: key); const AttributeSelection({Key? key, this.product, this.business, this.startKey}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ResponsiveBuilder( return ResponsiveBuilder(
builder: (context, sizingInformation) => builder: (context, sizingInformation) =>
ScreenTypeLayout( ScreenTypeLayout(
mobile: MobileAttributeSelection(product: product, business: business, startKey: startKey,), mobile: MobileAttributeSelection(product: product!, business: business!, startKey: startKey,),
tablet: MobileAttributeSelection(product: product, business: business, startKey: startKey,), tablet: MobileAttributeSelection(product: product!, business: business!, startKey: startKey,),
desktop: MobileAttributeSelection(product: product, business: business, startKey: startKey,), desktop: MobileAttributeSelection(product: product!, business: business!, startKey: startKey,),
), ),
); );
} }
+3 -3
View File
@@ -8,10 +8,10 @@ import '../widgets/desktop/desktop_blog.dart';
import '../widgets/mobile/mobile_blog.dart'; import '../widgets/mobile/mobile_blog.dart';
class Blog extends StatelessWidget { class Blog extends StatelessWidget {
final Key key; final Key? key;
final int businessId; final int businessId;
const Blog({this.key, int businessId}) : const Blog({this.key, int? businessId}) :
businessId = businessId ?? Constants.BUSINESS_ID; businessId = businessId ?? Constants.BUSINESS_ID;
@override @override
@@ -22,7 +22,7 @@ class Blog extends StatelessWidget {
mobile: MobileBlog(businessId: businessId,), mobile: MobileBlog(businessId: businessId,),
tablet: DesktopBlog(businessId: businessId,), tablet: DesktopBlog(businessId: businessId,),
desktop: Scrollbar( desktop: Scrollbar(
isAlwaysShown: true, thumbVisibility: true,
child: DesktopBlog(businessId: businessId,), child: DesktopBlog(businessId: businessId,),
), ),
), ),
+14 -10
View File
@@ -19,10 +19,10 @@ import '../widgets/mobile/mobile_renew_license.dart';
class BuyService extends StatefulWidget { class BuyService extends StatefulWidget {
final int gid; final int gid;
final String serviceName; final String serviceName;
final String domain; final String? domain;
final int sid; final int sid;
const BuyService(this.gid, this.serviceName, {Key key, this.domain, this.sid = 0}) : const BuyService(this.gid, this.serviceName, {Key? key, this.domain, this.sid = 0}) :
super(key: key); super(key: key);
@override @override
@@ -30,7 +30,7 @@ class BuyService extends StatefulWidget {
} }
class BuyServiceState extends State<BuyService> { class BuyServiceState extends State<BuyService> {
Map<String, dynamic> data; Map<String, dynamic>? data;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -51,9 +51,9 @@ class BuyServiceState extends State<BuyService> {
return ResponsiveBuilder( return ResponsiveBuilder(
builder: (context, sizingInformation) => builder: (context, sizingInformation) =>
ScreenTypeLayout( ScreenTypeLayout(
mobile: MobileBuyService(data), mobile: MobileBuyService(data!),
tablet: DesktopBuyService(data), tablet: DesktopBuyService(data!),
desktop: DesktopBuyService(data), desktop: DesktopBuyService(data!),
), ),
); );
} }
@@ -72,12 +72,16 @@ class BuyServiceState extends State<BuyService> {
'store_id': '${widget.sid}', 'store_id': '${widget.sid}',
} }
).then((value) { ).then((value) {
data = value; if (!mounted) return;
data['domain'] = widget.domain; if (value == null || value is! Map || value['service_selections'] == null) {
print('data: $data'); Utils.showMessageDialog(context, 'Service info unavailable');
return;
}
data = Map<String, dynamic>.from(value);
data!['domain'] = widget.domain;
setState(() {}); setState(() {});
}).onError((error, stackTrace) { }).onError((error, stackTrace) {
Utils.showMessageDialog(context, error); if (mounted) Utils.showMessageDialog(context, error);
}); });
} }
} }
+1 -1
View File
@@ -15,7 +15,7 @@ import '../widgets/mobile/mobile_change_mobile_or_email.dart';
class ChangeMobileOrEmail extends StatelessWidget { class ChangeMobileOrEmail extends StatelessWidget {
final bool isMobile; final bool isMobile;
const ChangeMobileOrEmail(this.isMobile, {Key key}) : super(key: key); const ChangeMobileOrEmail(this.isMobile, {Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
+1 -1
View File
@@ -11,7 +11,7 @@ import '../widgets/mobile/mobile_checkout.dart';
class Checkout extends StatelessWidget { class Checkout extends StatelessWidget {
final int businessId; final int businessId;
const Checkout(this.businessId, {Key key}) : const Checkout(this.businessId, {Key? key}) :
super(key: key); super(key: key);
@override @override
+7 -7
View File
@@ -12,9 +12,9 @@ import '../widgets/desktop/desktop_contact_us.dart';
import '../widgets/mobile/mobile_contact_us.dart'; import '../widgets/mobile/mobile_contact_us.dart';
class ContactUs extends StatefulWidget { class ContactUs extends StatefulWidget {
final int businessId; final int? businessId;
const ContactUs({this.businessId, Key key}) : const ContactUs({this.businessId, Key? key}) :
super(key: key); super(key: key);
@override @override
@@ -22,7 +22,7 @@ class ContactUs extends StatefulWidget {
} }
class ContactUsState extends State<ContactUs> { class ContactUsState extends State<ContactUs> {
Business business; Business? business;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -43,9 +43,9 @@ class ContactUsState extends State<ContactUs> {
return ResponsiveBuilder( return ResponsiveBuilder(
builder: (context, sizingInformation) => builder: (context, sizingInformation) =>
ScreenTypeLayout( ScreenTypeLayout(
mobile: MobileContactUs(business), mobile: MobileContactUs(business!),
tablet: DesktopContactUs(business), tablet: DesktopContactUs(business!),
desktop: DesktopContactUs(business), desktop: DesktopContactUs(business!),
), ),
); );
} }
@@ -59,7 +59,7 @@ class ContactUsState extends State<ContactUs> {
void loadData() { void loadData() {
HttpUtil.httpGet( HttpUtil.httpGet(
'v1/get-business', 'v1/get-business',
businessId: widget.businessId, businessId: widget.businessId!,
).then((value) { ).then((value) {
business = Business.fromJson(value); business = Business.fromJson(value);
setState(() {}); setState(() {});
+1 -1
View File
@@ -10,7 +10,7 @@ import '../widgets/mobile/mobile_coupons.dart';
class Coupons extends StatelessWidget { class Coupons extends StatelessWidget {
final int contactId; final int contactId;
const Coupons(this.contactId, {Key key}) : const Coupons(this.contactId, {Key? key}) :
super(key: key); super(key: key);
+1 -1
View File
@@ -11,7 +11,7 @@ import '../widgets/mobile/create_online_store_1.dart' as mobile;
class CreateOnlineStore1 extends StatefulWidget { class CreateOnlineStore1 extends StatefulWidget {
const CreateOnlineStore1({Key key}) : const CreateOnlineStore1({Key? key}) :
super(key: key); super(key: key);
@override @override
+6 -6
View File
@@ -30,7 +30,7 @@ class Download extends StatefulWidget {
class DownloadState extends State<Download> { class DownloadState extends State<Download> {
final _scaffoldKey = GlobalKey<ScaffoldState>(); final _scaffoldKey = GlobalKey<ScaffoldState>();
Map<String, dynamic> data; Map<String, dynamic>? data;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -58,11 +58,11 @@ class DownloadState extends State<Download> {
), ),
drawer: sizingInformation.deviceScreenType == DeviceScreenType.mobile ? MobileNavigationDrawer() : null, drawer: sizingInformation.deviceScreenType == DeviceScreenType.mobile ? MobileNavigationDrawer() : null,
body: ScreenTypeLayout( body: ScreenTypeLayout(
mobile: MobileDownloadApps(data), mobile: MobileDownloadApps(data!),
tablet: DesktopDownloadApps(data), tablet: DesktopDownloadApps(data!),
desktop: Scrollbar( desktop: Scrollbar(
isAlwaysShown: true, thumbVisibility: true,
child: DesktopDownloadApps(data), child: DesktopDownloadApps(data!),
), ),
), ),
bottomNavigationBar: ScreenTypeLayout( bottomNavigationBar: ScreenTypeLayout(
@@ -79,7 +79,7 @@ class DownloadState extends State<Download> {
super.initState(); super.initState();
eventBus.on<OpenDrawer>().listen((event) { eventBus.on<OpenDrawer>().listen((event) {
if (mounted) { if (mounted) {
_scaffoldKey.currentState.openDrawer(); _scaffoldKey.currentState!.openDrawer();
} }
}); });
_loadData(); _loadData();
+2 -2
View File
@@ -13,10 +13,10 @@ import '../widgets/general/navigationbar.dart';
import '../widgets/mobile/MobileBottomNav.dart'; import '../widgets/mobile/MobileBottomNav.dart';
class EditAddress extends StatelessWidget { class EditAddress extends StatelessWidget {
final Key key; final Key? key;
final Address address; final Address address;
final int businessId; final int businessId;
const EditAddress(this.address, {this.key, int businessId}) : const EditAddress(this.address, {this.key, int? businessId}) :
businessId = businessId ?? Constants.BUSINESS_ID; businessId = businessId ?? Constants.BUSINESS_ID;
@override @override
+1 -1
View File
@@ -12,7 +12,7 @@ import '../widgets/general/navigationbar.dart';
import '../widgets/mobile/MobileBottomNav.dart'; import '../widgets/mobile/MobileBottomNav.dart';
class ForgotPassword extends StatelessWidget { class ForgotPassword extends StatelessWidget {
const ForgotPassword({Key key}) : super(key: key); const ForgotPassword({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
+19 -18
View File
@@ -34,7 +34,7 @@ import '../widgets/mobile/mobile_navigation_drawer.dart';
class Home extends StatefulWidget { class Home extends StatefulWidget {
final String title; final String title;
Home({Key key, this.title = ''}) : super(key: key); Home({Key? key, this.title = ''}) : super(key: key);
@override @override
State<StatefulWidget> createState() { State<StatefulWidget> createState() {
@@ -46,11 +46,11 @@ class Home extends StatefulWidget {
class HomeState extends State<Home> { class HomeState extends State<Home> {
final _scaffoldKey = GlobalKey<ScaffoldState>(); final _scaffoldKey = GlobalKey<ScaffoldState>();
List<Gallery> galleries = []; List<Gallery> galleries = [];
String content1Message; String? content1Message;
Map<String, dynamic> content2; Map<String, dynamic>? content2;
StreamSubscription _sub; StreamSubscription? _sub;
Uri _latestUri; Uri? _latestUri;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -80,9 +80,9 @@ class HomeState extends State<Home> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
MobileIndexCarousel(galleries), MobileIndexCarousel(galleries),
MobileIndexMainContent1(content1Message), MobileIndexMainContent1(content1Message ?? ''),
MobileIndexMainContent2(content2), MobileIndexMainContent2(content2 ?? <String, dynamic>{}),
MobileIndexMainContent3(content2), MobileIndexMainContent3(content2 ?? <String, dynamic>{}),
], ],
), ),
), ),
@@ -91,24 +91,25 @@ class HomeState extends State<Home> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
DesktopIndexCarousel(galleries), DesktopIndexCarousel(galleries),
DesktopIndexMainContent1(content1Message), DesktopIndexMainContent1(content1Message ?? ''),
DesktopIndexMainContent2(content2), DesktopIndexMainContent2(content2 ?? <String, dynamic>{}),
CustomersLogo(), CustomersLogo(),
DesktopIndexMainContent3(content2), DesktopIndexMainContent3(content2 ?? <String, dynamic>{}),
], ],
), ),
), ),
desktop: Scrollbar( desktop: Scrollbar(
isAlwaysShown: true, thumbVisibility: true,
child: SingleChildScrollView( child: SingleChildScrollView(
primary: true,
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
DesktopIndexCarousel(galleries), DesktopIndexCarousel(galleries),
DesktopIndexMainContent1(content1Message), DesktopIndexMainContent1(content1Message ?? ''),
DesktopIndexMainContent2(content2), DesktopIndexMainContent2(content2 ?? <String, dynamic>{}),
CustomersLogo(), CustomersLogo(),
DesktopIndexMainContent3(content2), DesktopIndexMainContent3(content2 ?? <String, dynamic>{}),
], ],
), ),
), ),
@@ -136,7 +137,7 @@ class HomeState extends State<Home> {
_loadData(); _loadData();
eventBus.on<OpenDrawer>().listen((event) { eventBus.on<OpenDrawer>().listen((event) {
if (mounted) { if (mounted) {
_scaffoldKey.currentState.openDrawer(); _scaffoldKey.currentState?.openDrawer();
} }
}); });
WidgetsBinding.instance.addPostFrameCallback((timeStamp) { WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
@@ -163,7 +164,7 @@ class HomeState extends State<Home> {
if (!mounted) return; if (!mounted) return;
_latestUri = Uri.base; _latestUri = Uri.base;
print('uri base $_latestUri'); print('uri base $_latestUri');
eventBus.fire(OnGotDeepLinkUri(_latestUri)); eventBus.fire(OnGotDeepLinkUri(_latestUri!));
} else { } else {
// _sub = getUriLinksStream().listen((Uri uri) { // _sub = getUriLinksStream().listen((Uri uri) {
// print('_sub should get uri $uri'); // print('_sub should get uri $uri');
@@ -189,7 +190,7 @@ class HomeState extends State<Home> {
// //
// if (!mounted) return; // if (!mounted) return;
// _latestUri = initialUri; // _latestUri = initialUri;
// eventBus.fire(OnGotDeepLinkUri(_latestUri)); // eventBus.fire(OnGotDeepLinkUri(_latestUri!));
} }
} }
} }
+5 -5
View File
@@ -16,7 +16,7 @@ import '../widgets/mobile/MobileBottomNav.dart';
import '../widgets/mobile/mobile_igoshow_learn_more.dart'; import '../widgets/mobile/mobile_igoshow_learn_more.dart';
class IGoShowLearnMore extends StatefulWidget { class IGoShowLearnMore extends StatefulWidget {
const IGoShowLearnMore({Key key}) : super(key: key); const IGoShowLearnMore({Key? key}) : super(key: key);
@override @override
State<StatefulWidget> createState() { State<StatefulWidget> createState() {
@@ -26,7 +26,7 @@ class IGoShowLearnMore extends StatefulWidget {
class IGoShowLearnMoreState extends State<IGoShowLearnMore> { class IGoShowLearnMoreState extends State<IGoShowLearnMore> {
final _scaffoldKey = GlobalKey<ScaffoldState>(); final _scaffoldKey = GlobalKey<ScaffoldState>();
Map<String, dynamic> data; Map<String, dynamic>? data;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -56,9 +56,9 @@ class IGoShowLearnMoreState extends State<IGoShowLearnMore> {
), ),
drawer: null, drawer: null,
body: ScreenTypeLayout( body: ScreenTypeLayout(
mobile: MobileiGoShowLearnMore(data), mobile: MobileiGoShowLearnMore(data!),
tablet: DesktopiGoShowLearnMore(data), tablet: DesktopiGoShowLearnMore(data!),
desktop: DesktopiGoShowLearnMore(data), desktop: DesktopiGoShowLearnMore(data!),
), ),
bottomNavigationBar: ScreenTypeLayout( bottomNavigationBar: ScreenTypeLayout(
mobile: MobileBottomNav(currentIndex: 0,), mobile: MobileBottomNav(currentIndex: 0,),
+1 -1
View File
@@ -14,7 +14,7 @@ import '../widgets/mobile/MobileBottomNav.dart';
import '../widgets/mobile/mobile_login.dart'; import '../widgets/mobile/mobile_login.dart';
class Login extends StatefulWidget { class Login extends StatefulWidget {
final Key key; final Key? key;
const Login({this.key}) : super(key: key); const Login({this.key}) : super(key: key);
+1 -1
View File
@@ -15,7 +15,7 @@ import '../widgets/mobile/MobileBottomNav.dart';
import '../widgets/mobile/mobile_me.dart'; import '../widgets/mobile/mobile_me.dart';
class Me extends StatefulWidget { class Me extends StatefulWidget {
final Key key; final Key? key;
const Me({this.key}) : super(key: key); const Me({this.key}) : super(key: key);
+5 -5
View File
@@ -16,7 +16,7 @@ import '../widgets/mobile/MobileBottomNav.dart';
import '../widgets/mobile/mobile_minipos_learn_more.dart'; import '../widgets/mobile/mobile_minipos_learn_more.dart';
class MiniPosLearnMore extends StatefulWidget { class MiniPosLearnMore extends StatefulWidget {
const MiniPosLearnMore({Key key}) : super(key: key); const MiniPosLearnMore({Key? key}) : super(key: key);
@override @override
State<StatefulWidget> createState() { State<StatefulWidget> createState() {
@@ -26,7 +26,7 @@ class MiniPosLearnMore extends StatefulWidget {
class MiniPosLearnMoreState extends State<MiniPosLearnMore> { class MiniPosLearnMoreState extends State<MiniPosLearnMore> {
final _scaffoldKey = GlobalKey<ScaffoldState>(); final _scaffoldKey = GlobalKey<ScaffoldState>();
Map<String, dynamic> data; Map<String, dynamic>? data;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -57,9 +57,9 @@ class MiniPosLearnMoreState extends State<MiniPosLearnMore> {
), ),
drawer: null, drawer: null,
body: ScreenTypeLayout( body: ScreenTypeLayout(
mobile: MobileMiniPosLearnMore(data), mobile: MobileMiniPosLearnMore(data!),
tablet: DesktopMiniPosLearnMore(data), tablet: DesktopMiniPosLearnMore(data!),
desktop: DesktopMiniPosLearnMore(data), desktop: DesktopMiniPosLearnMore(data!),
), ),
bottomNavigationBar: ScreenTypeLayout( bottomNavigationBar: ScreenTypeLayout(
mobile: MobileBottomNav(currentIndex: 0,), mobile: MobileBottomNav(currentIndex: 0,),
+2 -2
View File
@@ -8,10 +8,10 @@ import '../widgets/desktop/desktop_my_addresses.dart';
import '../widgets/mobile/mobile_my_addresses.dart'; import '../widgets/mobile/mobile_my_addresses.dart';
class MyAddresses extends StatelessWidget { class MyAddresses extends StatelessWidget {
final Key key; final Key? key;
final int businessId; final int businessId;
const MyAddresses({this.key, int businessId}) : const MyAddresses({this.key, int? businessId}) :
businessId = businessId ?? Constants.BUSINESS_ID; businessId = businessId ?? Constants.BUSINESS_ID;
@override @override
+2 -2
View File
@@ -8,10 +8,10 @@ import '../widgets/desktop/desktop_my_support.dart';
import '../widgets/mobile/mobile_my_support.dart'; import '../widgets/mobile/mobile_my_support.dart';
class MySupport extends StatelessWidget { class MySupport extends StatelessWidget {
final Key key; final Key? key;
final int businessId; final int businessId;
const MySupport({this.key, int businessId}) : const MySupport({this.key, int? businessId}) :
businessId = businessId ?? Constants.BUSINESS_ID; businessId = businessId ?? Constants.BUSINESS_ID;
@override @override
+3 -3
View File
@@ -7,9 +7,9 @@ import '../widgets/desktop/desktop_new_address.dart';
import '../widgets/mobile/mobile_new_address.dart'; import '../widgets/mobile/mobile_new_address.dart';
class NewAddress extends StatelessWidget { class NewAddress extends StatelessWidget {
final Key key; final Key? key;
final LocatedAddress locatedAddress; final LocatedAddress? locatedAddress;
final int businessId; final int? businessId;
const NewAddress({this.key, this.locatedAddress, this.businessId}) : super(key: key); const NewAddress({this.key, this.locatedAddress, this.businessId}) : super(key: key);
@override @override
+1 -1
View File
@@ -10,7 +10,7 @@ import '../widgets/mobile/mobile_new_comment.dart';
class NewComment extends StatelessWidget { class NewComment extends StatelessWidget {
final int orderId; final int orderId;
const NewComment(this.orderId, {Key key}) : const NewComment(this.orderId, {Key? key}) :
super(key: key); super(key: key);
+2 -2
View File
@@ -14,10 +14,10 @@ import '../widgets/mobile/MobileBottomNav.dart';
import '../widgets/mobile/mobile_new_ticket.dart'; import '../widgets/mobile/mobile_new_ticket.dart';
class NewTicket extends StatefulWidget { class NewTicket extends StatefulWidget {
final Key key; final Key? key;
final int businessId; final int businessId;
const NewTicket({this.key, int businessId}) : const NewTicket({this.key, int? businessId}) :
businessId = businessId ?? Constants.BUSINESS_ID; businessId = businessId ?? Constants.BUSINESS_ID;
@override @override
+1 -1
View File
@@ -12,7 +12,7 @@ import '../widgets/mobile/MobileBottomNav.dart';
import '../widgets/mobile/mobile_new_user.dart'; import '../widgets/mobile/mobile_new_user.dart';
class NewUser extends StatelessWidget { class NewUser extends StatelessWidget {
const NewUser({Key key}) : super(key: key); const NewUser({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
+1 -1
View File
@@ -11,7 +11,7 @@ class OrderDetail extends StatelessWidget {
final int orderId; final int orderId;
final bool fromOrders; final bool fromOrders;
const OrderDetail(this.orderId, {this.fromOrders = false, Key key}) : const OrderDetail(this.orderId, {this.fromOrders = false, Key? key}) :
super(key: key); super(key: key);
@override @override
+1 -1
View File
@@ -10,7 +10,7 @@ import '../widgets/mobile/mobile_pay_now.dart';
class PayNow extends StatelessWidget { class PayNow extends StatelessWidget {
final int orderId; final int orderId;
const PayNow(this.orderId, {Key key}) : const PayNow(this.orderId, {Key? key}) :
super(key: key); super(key: key);
+7 -7
View File
@@ -12,10 +12,10 @@ import '../utils/http_util.dart';
import '../utils/utils.dart'; import '../utils/utils.dart';
class PlainPage extends StatefulWidget { class PlainPage extends StatefulWidget {
final int businessId; final int? businessId;
final String slug; final String slug;
const PlainPage(this.slug, {this.businessId, Key key}) : const PlainPage(this.slug, {this.businessId, Key? key}) :
super(key: key); super(key: key);
@override @override
@@ -23,7 +23,7 @@ class PlainPage extends StatefulWidget {
} }
class PlainPageState extends State<PlainPage> { class PlainPageState extends State<PlainPage> {
Blog blog; Blog? blog;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -44,9 +44,9 @@ class PlainPageState extends State<PlainPage> {
return ResponsiveBuilder( return ResponsiveBuilder(
builder: (context, sizingInformation) => builder: (context, sizingInformation) =>
ScreenTypeLayout( ScreenTypeLayout(
mobile: MobilePlainPage(blog), mobile: MobilePlainPage(blog!),
tablet: DesktopPlainPage(blog), tablet: DesktopPlainPage(blog!),
desktop: DesktopPlainPage(blog), desktop: DesktopPlainPage(blog!),
), ),
); );
} }
@@ -60,7 +60,7 @@ class PlainPageState extends State<PlainPage> {
void loadData() { void loadData() {
HttpUtil.httpGet( HttpUtil.httpGet(
'v1/special-page', 'v1/special-page',
businessId: widget.businessId, businessId: widget.businessId!,
queryParameters: { queryParameters: {
'bid': widget.slug, 'bid': widget.slug,
} }
+6 -6
View File
@@ -10,10 +10,10 @@ import '../widgets/desktop/desktop_product_detail_page.dart';
import '../widgets/mobile/mobile_product_detail_page.dart'; import '../widgets/mobile/mobile_product_detail_page.dart';
class ProductDetailPage extends StatelessWidget { class ProductDetailPage extends StatelessWidget {
final Business business; final Business? business;
final Product product; final Product? product;
const ProductDetailPage({this.business, this.product, Key key}) : const ProductDetailPage({this.business, this.product, Key? key}) :
super(key: key); super(key: key);
@@ -24,9 +24,9 @@ class ProductDetailPage extends StatelessWidget {
return ResponsiveBuilder( return ResponsiveBuilder(
builder: (context, sizingInformation) => builder: (context, sizingInformation) =>
ScreenTypeLayout( ScreenTypeLayout(
mobile: MobileProductDetailPage(business: business, product: product,), mobile: MobileProductDetailPage(business: business!, product: product!,),
tablet: DesktopProductDetailPage(business: business, product: product,), tablet: DesktopProductDetailPage(business: business!, product: product!,),
desktop: DesktopProductDetailPage(business: business, product: product,), desktop: DesktopProductDetailPage(business: business!, product: product!,),
), ),
); );
} }
+1 -1
View File
@@ -9,7 +9,7 @@ import '../widgets/mobile/product_search.dart' as mobile;
class ProductSearch extends StatelessWidget { class ProductSearch extends StatelessWidget {
final Business business; final Business business;
const ProductSearch(this.business, {Key key}) : super(key: key); const ProductSearch(this.business, {Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
+1 -1
View File
@@ -12,7 +12,7 @@ import '../widgets/mobile/mobile_renew_license.dart';
class RenewLicense extends StatefulWidget { class RenewLicense extends StatefulWidget {
const RenewLicense({Key key}) : const RenewLicense({Key? key}) :
super(key: key); super(key: key);
@override @override
+5 -5
View File
@@ -17,7 +17,7 @@ import '../widgets/mobile/mobile_renew_license.dart';
class RenewMiniOffice extends StatefulWidget { class RenewMiniOffice extends StatefulWidget {
final int gid; final int gid;
const RenewMiniOffice(this.gid, {Key key}) : const RenewMiniOffice(this.gid, {Key? key}) :
super(key: key); super(key: key);
@override @override
@@ -25,7 +25,7 @@ class RenewMiniOffice extends StatefulWidget {
} }
class RenewMiniOfficeState extends State<RenewMiniOffice> { class RenewMiniOfficeState extends State<RenewMiniOffice> {
Map<String, dynamic> data; Map<String, dynamic>? data;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -46,9 +46,9 @@ class RenewMiniOfficeState extends State<RenewMiniOffice> {
return ResponsiveBuilder( return ResponsiveBuilder(
builder: (context, sizingInformation) => builder: (context, sizingInformation) =>
ScreenTypeLayout( ScreenTypeLayout(
mobile: MobileRenewMiniOffice(data), mobile: MobileRenewMiniOffice(data!),
tablet: DesktopRenewMiniOffice(data), tablet: DesktopRenewMiniOffice(data!),
desktop: DesktopRenewMiniOffice(data), desktop: DesktopRenewMiniOffice(data!),
), ),
); );
} }
+2 -2
View File
@@ -13,8 +13,8 @@ import '../widgets/mobile/mobile_reset_password.dart';
class ResetPassword extends StatelessWidget { class ResetPassword extends StatelessWidget {
final String mobile; final String mobile;
final String code; final String? code;
const ResetPassword(this.mobile, {Key key, this.code}) : super(key: key); const ResetPassword(this.mobile, {Key? key, this.code}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
+1 -1
View File
@@ -5,7 +5,7 @@ import '../widgets/mobile/mobile_search_place.dart';
import 'package:responsive_builder/responsive_builder.dart'; import 'package:responsive_builder/responsive_builder.dart';
class SearchPlace extends StatelessWidget { class SearchPlace extends StatelessWidget {
final Key key; final Key? key;
final int businessId; final int businessId;
const SearchPlace(this.businessId, {this.key}) : super(key: key); const SearchPlace(this.businessId, {this.key}) : super(key: key);
+2 -2
View File
@@ -13,8 +13,8 @@ import '../widgets/mobile/mobile_set_password.dart';
class SetPassword extends StatelessWidget { class SetPassword extends StatelessWidget {
final String mobile; final String mobile;
final String code; final String? code;
const SetPassword(this.mobile, {Key key, this.code}) : super(key: key); const SetPassword(this.mobile, {Key? key, this.code}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
+3 -3
View File
@@ -8,9 +8,9 @@ import '../widgets/desktop/shop.dart' as desktop;
import '../widgets/mobile/shop.dart' as mobile; import '../widgets/mobile/shop.dart' as mobile;
class Shop extends StatefulWidget { class Shop extends StatefulWidget {
final int businessId; final int? businessId;
const Shop({this.businessId, Key key}) : super(key: key); const Shop({this.businessId, Key? key}) : super(key: key);
@override @override
State<StatefulWidget> createState() => ShopState(); State<StatefulWidget> createState() => ShopState();
@@ -20,7 +20,7 @@ class ShopState extends State<Shop> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
int _businessId = int _businessId =
widget.businessId == null ? Utils.getBusinessId() : widget.businessId; widget.businessId == null ? Utils.getBusinessId() : widget.businessId!;
return ResponsiveBuilder( return ResponsiveBuilder(
builder: (context, sizingInformation) => ScreenTypeLayout( builder: (context, sizingInformation) => ScreenTypeLayout(
+1 -1
View File
@@ -15,7 +15,7 @@ import '../widgets/mobile/mobile_store_product_search.dart';
class StoreProductSearch extends StatelessWidget { class StoreProductSearch extends StatelessWidget {
final Business business; final Business business;
const StoreProductSearch(this.business, {Key key}) : super(key: key); const StoreProductSearch(this.business, {Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
-34
View File
@@ -1,34 +0,0 @@
import 'package:flutter/material.dart';
import 'package:responsive_builder/responsive_builder.dart';
import '../models/order.dart';
import '../models/payment_platform.dart';
import '../models/stripe_payment_method.dart';
import '../store/actions.dart';
import '../store/store.dart';
import '../widgets/desktop/desktop_stripe_pay_web.dart';
import '../widgets/mobile/mobile_stripe_pay_web.dart';
class StripePayWeb extends StatelessWidget {
final Order order;
final PaymentPlatform paymentPlatform;
final StripePaymentMethod stripePaymentMethod;
const StripePayWeb(this.order, this.paymentPlatform, {this.stripePaymentMethod});
@override
Widget build(BuildContext context) {
store.dispatch(UpdateContext(context));
return ResponsiveBuilder(
builder: (context, sizingInformation) =>
ScreenTypeLayout(
mobile: MobileStripePayWeb(order, paymentPlatform, stripePaymentMethod: stripePaymentMethod,),
tablet: DesktopStripePayWeb(order, paymentPlatform, stripePaymentMethod: stripePaymentMethod,),
desktop: DesktopStripePayWeb(order, paymentPlatform, stripePaymentMethod: stripePaymentMethod,),
),
);
}
}
+1 -1
View File
@@ -13,7 +13,7 @@ import '../widgets/mobile/MobileBottomNav.dart';
import '../widgets/mobile/mobile_user_profile.dart'; import '../widgets/mobile/mobile_user_profile.dart';
class UserProfile extends StatelessWidget { class UserProfile extends StatelessWidget {
const UserProfile({Key key}) : super(key: key); const UserProfile({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
+1 -1
View File
@@ -14,7 +14,7 @@ import '../widgets/mobile/MobileBottomNav.dart';
import '../widgets/mobile/mobile_view_blog.dart'; import '../widgets/mobile/mobile_view_blog.dart';
class ViewBlog extends StatefulWidget { class ViewBlog extends StatefulWidget {
final Key key; final Key? key;
final int bid; final int bid;
const ViewBlog(this.bid, {this.key}) : super(key: key); const ViewBlog(this.bid, {this.key}) : super(key: key);
+1 -1
View File
@@ -14,7 +14,7 @@ import '../widgets/mobile/MobileBottomNav.dart';
import '../widgets/mobile/mobile_view_ticket.dart'; import '../widgets/mobile/mobile_view_ticket.dart';
class ViewTicket extends StatefulWidget { class ViewTicket extends StatefulWidget {
final Key key; final Key? key;
final int ticketId; final int ticketId;
const ViewTicket(this.ticketId, {this.key}) : super(key: key); const ViewTicket(this.ticketId, {this.key}) : super(key: key);
+58 -58
View File
@@ -44,169 +44,169 @@ class Routes {
static void configure() { static void configure() {
router.define('/', handler: new Handler( router.define('/', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return Home(title: Constants.APP_TITLE,); return Home(title: Constants.APP_TITLE,);
}), }),
transitionType: TransitionType.fadeIn transitionType: TransitionType.fadeIn
); );
router.define('/download', handler: new Handler( router.define('/download', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return Download(); return Download();
}), }),
transitionType: TransitionType.inFromRight transitionType: TransitionType.inFromRight
); );
router.define('/minipos-learn-more', handler: new Handler( router.define('/minipos-learn-more', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return MiniPosLearnMore(); return MiniPosLearnMore();
}), }),
transitionType: TransitionType.inFromRight transitionType: TransitionType.inFromRight
); );
router.define('/igoshow-learn-more', handler: new Handler( router.define('/igoshow-learn-more', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return IGoShowLearnMore(); return IGoShowLearnMore();
}), }),
transitionType: TransitionType.inFromRight transitionType: TransitionType.inFromRight
); );
router.define('/login', handler: new Handler( router.define('/login', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return Login(); return Login();
}), }),
transitionType: TransitionType.inFromRight transitionType: TransitionType.inFromRight
); );
router.define('/me', handler: new Handler( router.define('/me', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return Me(); return Me();
}), }),
transitionType: TransitionType.inFromRight transitionType: TransitionType.inFromRight
); );
router.define('/change-password', handler: new Handler( router.define('/change-password', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return ChangePassword(); return ChangePassword();
}), }),
transitionType: TransitionType.inFromRight transitionType: TransitionType.inFromRight
); );
router.define('/user-profile', handler: new Handler( router.define('/user-profile', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return UserProfile(); return UserProfile();
}), }),
transitionType: TransitionType.inFromRight transitionType: TransitionType.inFromRight
); );
router.define('/new-user', handler: new Handler( router.define('/new-user', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return NewUser(); return NewUser();
}), }),
transitionType: TransitionType.inFromRight transitionType: TransitionType.inFromRight
); );
router.define('/set-password/:mobile/:code', handler: new Handler( router.define('/set-password/:mobile/:code', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return SetPassword(params['mobile'][0], code: params['code'][0]); return SetPassword(params['mobile']![0], code: params['code']![0]);
} }
)); ));
router.define('/forgot-password', handler: new Handler( router.define('/forgot-password', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return ForgotPassword(); return ForgotPassword();
} }
)); ));
router.define('/reset-password/:mobile/:code', handler: new Handler( router.define('/reset-password/:mobile/:code', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return ResetPassword(params['mobile'][0], code: params['code'][0]); return ResetPassword(params['mobile']![0], code: params['code']![0]);
} }
)); ));
router.define('/change-mobile-email/:ismobile', handler: new Handler( router.define('/change-mobile-email/:ismobile', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
if (params['ismobile'][0] == '1') { if (params['ismobile']![0] == '1') {
return ChangeMobileOrEmail(true); return ChangeMobileOrEmail(true);
} }
return ChangeMobileOrEmail(false); return ChangeMobileOrEmail(false);
} }
)); ));
router.define('/my-addresses/:business_id', handler: new Handler( router.define('/my-addresses/:business_id', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return MyAddresses(businessId: int.parse(params['business_id'][0]),); return MyAddresses(businessId: int.parse(params['business_id']![0]),);
} }
)); ));
router.define('/my-support/:business_id', handler: new Handler( router.define('/my-support/:business_id', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return MySupport(businessId: int.parse(params['business_id'][0]),); return MySupport(businessId: int.parse(params['business_id']![0]),);
} }
)); ));
router.define('/new-ticket/:business_id', handler: new Handler( router.define('/new-ticket/:business_id', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return NewTicket(businessId: int.parse(params['business_id'][0]),); return NewTicket(businessId: int.parse(params['business_id']![0]),);
} }
)); ));
router.define('/search-place/:business_id', handler: new Handler( router.define('/search-place/:business_id', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return SearchPlace(int.parse(params['business_id'][0])); return SearchPlace(int.parse(params['business_id']![0]));
} }
)); ));
router.define('/view-ticket/:ticket_id', handler: new Handler( router.define('/view-ticket/:ticket_id', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return ViewTicket(int.parse(params['ticket_id'][0]),); return ViewTicket(int.parse(params['ticket_id']![0]),);
} }
)); ));
router.define('/blog/:business_id', handler: new Handler( router.define('/blog/:business_id', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return Blog(businessId: int.parse(params['business_id'][0]),); return Blog(businessId: int.parse(params['business_id']![0]),);
} }
)); ));
router.define('/view-blog/:bid', handler: new Handler( router.define('/view-blog/:bid', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return ViewBlog(int.parse(params['bid'][0]),); return ViewBlog(int.parse(params['bid']![0]),);
} }
)); ));
router.define('/shop/:business_id', handler: new Handler( router.define('/shop/:business_id', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return Shop(businessId: int.parse(params['business_id'][0]),); return Shop(businessId: int.parse(params['business_id']![0]),);
} }
)); ));
router.define('/shop', handler: new Handler( router.define('/shop', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return Shop(); return Shop();
} }
)); ));
// router.define('/ocr-scan', handler: new Handler( // router.define('/ocr-scan', handler: new Handler(
// handlerFunc: (BuildContext context, Map<String, List<String>> params) { // handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
// return OCRScan(); // return OCRScan();
// } // }
// )); // ));
router.define('/checkout/:id', handler: new Handler( router.define('/checkout/:id', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return Checkout(int.parse(params['id'][0])); return Checkout(int.parse(params['id']![0]));
}), }),
); );
router.define('/paynow/:orderId', handler: new Handler( router.define('/paynow/:orderId', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return PayNow(int.parse(params['orderId'][0])); return PayNow(int.parse(params['orderId']![0]));
}), }),
); );
router.define('/orders', handler: new Handler( router.define('/orders', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return Orders(); return Orders();
} }
)); ));
router.define('/my-cards', handler: new Handler( router.define('/my-cards', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return MyCards(); return MyCards();
} }
)); ));
router.define('/orderdetail/:orderId', handler: new Handler( router.define('/orderdetail/:orderId', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return OrderDetail(int.parse(params['orderId'][0])); return OrderDetail(int.parse(params['orderId']![0]));
}), }),
); );
router.define('/new-comment/:orderId', handler: new Handler( router.define('/new-comment/:orderId', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return NewComment(int.parse(params['orderId'][0])); return NewComment(int.parse(params['orderId']![0]));
}), }),
); );
router.define('/coupons/:contactId', handler: new Handler( router.define('/coupons/:contactId', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return Coupons(int.parse(params['contactId'][0])); return Coupons(int.parse(params['contactId']![0]));
}), }),
); );
router.define('/service-policy', handler: new Handler( router.define('/service-policy', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return PlainPage( return PlainPage(
'service-policy', 'service-policy',
// businessId: Constants.BUSINESS_ID, // businessId: Constants.BUSINESS_ID,
@@ -215,7 +215,7 @@ class Routes {
}), }),
); );
router.define('/return-policy', handler: new Handler( router.define('/return-policy', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return PlainPage( return PlainPage(
'return-policy', 'return-policy',
// businessId: Constants.BUSINESS_ID, // businessId: Constants.BUSINESS_ID,
@@ -224,7 +224,7 @@ class Routes {
}), }),
); );
router.define('/privacy-policy', handler: new Handler( router.define('/privacy-policy', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return PlainPage( return PlainPage(
'privacy-policy', 'privacy-policy',
// businessId: Constants.BUSINESS_ID, // businessId: Constants.BUSINESS_ID,
@@ -233,7 +233,7 @@ class Routes {
}), }),
); );
router.define('/end-user-license-agreement', handler: new Handler( router.define('/end-user-license-agreement', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return PlainPage( return PlainPage(
'end-user-license-agreement', 'end-user-license-agreement',
// businessId: Constants.BUSINESS_ID, // businessId: Constants.BUSINESS_ID,
@@ -242,7 +242,7 @@ class Routes {
}), }),
); );
router.define('/about-us', handler: new Handler( router.define('/about-us', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return PlainPage( return PlainPage(
'about-us', 'about-us',
// businessId: Constants.BUSINESS_ID, // businessId: Constants.BUSINESS_ID,
@@ -251,29 +251,29 @@ class Routes {
}), }),
); );
router.define('/contact-us', handler: new Handler( router.define('/contact-us', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return ContactUs( return ContactUs(
businessId: Constants.BUSINESS_ID, businessId: Constants.BUSINESS_ID,
); );
}), }),
); );
router.define('/renew-license', handler: new Handler( router.define('/renew-license', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return RenewLicense(); return RenewLicense();
} }
)); ));
router.define('/renew-minioffice/:gid', handler: new Handler( router.define('/renew-minioffice/:gid', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return RenewMiniOffice(int.parse(params['gid'][0])); return RenewMiniOffice(int.parse(params['gid']![0]));
} }
)); ));
router.define('/buy-service/:gid/:servicename', handler: new Handler( router.define('/buy-service/:gid/:servicename', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return BuyService(int.parse(params['gid'][0]), params['servicename'][0]); return BuyService(int.parse(params['gid']![0]), params['servicename']![0]);
} }
)); ));
router.define('/contact-stores', handler: new Handler( router.define('/contact-stores', handler: new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) { handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return CreateOnlineStore1(); return CreateOnlineStore1();
} }
)); ));
+2 -2
View File
@@ -15,12 +15,12 @@ class UpdateLocale {
} }
class UpdateCurrentUser { class UpdateCurrentUser {
final User user; final User? user;
UpdateCurrentUser(this.user); UpdateCurrentUser(this.user);
} }
class UpdateRedirectRoute { class UpdateRedirectRoute {
final String route; final String? route;
UpdateRedirectRoute(this.route); UpdateRedirectRoute(this.route);
} }
+3 -3
View File
@@ -4,10 +4,10 @@ import 'package:redux/redux.dart';
import '../actions.dart'; import '../actions.dart';
final cartInfoReducer = combineReducers<List<CartInfo>>([ final cartInfoReducer = combineReducers<List<CartInfo>?>([
TypedReducer<List<CartInfo>, UpdateCartInfo>(_updateCartInfo) TypedReducer<List<CartInfo>?, UpdateCartInfo>(_updateCartInfo)
]); ]);
List<CartInfo> _updateCartInfo(List<CartInfo> cartInfos, action) { List<CartInfo>? _updateCartInfo(List<CartInfo>? cartInfos, action) {
return action.cartInfos; return action.cartInfos;
} }
+3 -3
View File
@@ -3,10 +3,10 @@ import 'package:flutter/material.dart';
import 'package:flutter_wisetronic/store/actions.dart'; import 'package:flutter_wisetronic/store/actions.dart';
import 'package:redux/redux.dart'; import 'package:redux/redux.dart';
final contextReducer = combineReducers<BuildContext>([ final contextReducer = combineReducers<BuildContext?>([
TypedReducer<BuildContext, UpdateContext>(_updateContext) TypedReducer<BuildContext?, UpdateContext>(_updateContext)
]); ]);
BuildContext _updateContext(BuildContext context, action) { BuildContext? _updateContext(BuildContext? context, action) {
return action.context; return action.context;
} }
+3 -3
View File
@@ -2,10 +2,10 @@ import 'package:redux/redux.dart';
import '../actions.dart'; import '../actions.dart';
final deviceIdReducer = combineReducers<String>([ final deviceIdReducer = combineReducers<String?>([
TypedReducer<String, UpdateDeviceId>(_updateDeviceId) TypedReducer<String?, UpdateDeviceId>(_updateDeviceId)
]); ]);
String _updateDeviceId(String deviceId, action) { String? _updateDeviceId(String? deviceId, action) {
return action.deviceId; return action.deviceId;
} }
+3 -3
View File
@@ -2,10 +2,10 @@ import 'package:redux/redux.dart';
import '../actions.dart'; import '../actions.dart';
final fcmtokenReducer = combineReducers<String>([ final fcmtokenReducer = combineReducers<String?>([
TypedReducer<String, UpdateFcmToken>(_updateFcmToken) TypedReducer<String?, UpdateFcmToken>(_updateFcmToken)
]); ]);
String _updateFcmToken(String token, action) { String? _updateFcmToken(String? token, action) {
return action.token; return action.token;
} }
+3 -3
View File
@@ -2,10 +2,10 @@ import 'package:redux/redux.dart';
import '../actions.dart'; import '../actions.dart';
final lastVisitReducer = combineReducers<List<int>>([ final lastVisitReducer = combineReducers<List<int>?>([
TypedReducer<List<int>, UpdateLastVisit>(_updateLastVisit) TypedReducer<List<int>?, UpdateLastVisit>(_updateLastVisit)
]); ]);
List<int> _updateLastVisit(List<int> lastVisit, action) { List<int>? _updateLastVisit(List<int>? lastVisit, action) {
return action.lastVisit; return action.lastVisit;
} }
+3 -3
View File
@@ -2,10 +2,10 @@ import 'package:flutter/material.dart';
import 'package:flutter_wisetronic/store/actions.dart'; import 'package:flutter_wisetronic/store/actions.dart';
import 'package:redux/redux.dart'; import 'package:redux/redux.dart';
final localeReducer = combineReducers<Locale>([ final localeReducer = combineReducers<Locale?>([
TypedReducer<Locale, UpdateLocale>(_updateLocale) TypedReducer<Locale?, UpdateLocale>(_updateLocale)
]); ]);
Locale _updateLocale(Locale locale, action) { Locale? _updateLocale(Locale? locale, action) {
return action.locale; return action.locale;
} }
@@ -3,10 +3,10 @@ import 'package:redux/redux.dart';
import '../../models/located_address.dart'; import '../../models/located_address.dart';
import '../actions.dart'; import '../actions.dart';
final locatedAddressReducer = combineReducers<LocatedAddress>([ final locatedAddressReducer = combineReducers<LocatedAddress?>([
TypedReducer<LocatedAddress, UpdateLocatedAddress>(_updateLocatedAddress) TypedReducer<LocatedAddress?, UpdateLocatedAddress>(_updateLocatedAddress)
]); ]);
LocatedAddress _updateLocatedAddress(LocatedAddress locatedAddress, action) { LocatedAddress? _updateLocatedAddress(LocatedAddress? locatedAddress, action) {
return action.locatedAddress; return action.locatedAddress;
} }
@@ -2,10 +2,10 @@
import 'package:redux/redux.dart'; import 'package:redux/redux.dart';
import '../actions.dart'; import '../actions.dart';
final redirectRouteReducer = combineReducers<String>([ final redirectRouteReducer = combineReducers<String?>([
TypedReducer<String, UpdateRedirectRoute>(_updateRedirectRoute) TypedReducer<String?, UpdateRedirectRoute>(_updateRedirectRoute)
]); ]);
String _updateRedirectRoute(String route, action) { String? _updateRedirectRoute(String? route, action) {
return action.route; return action.route;
} }
+3 -3
View File
@@ -2,10 +2,10 @@ import 'package:redux/redux.dart';
import '../actions.dart'; import '../actions.dart';
final tableNumberReducer = combineReducers<String>([ final tableNumberReducer = combineReducers<String?>([
TypedReducer<String, UpdateTableNumber>(_updateTableNumber) TypedReducer<String?, UpdateTableNumber>(_updateTableNumber)
]); ]);
String _updateTableNumber(String tableNumber, action) { String? _updateTableNumber(String? tableNumber, action) {
return action.tableNumber; return action.tableNumber;
} }
+3 -3
View File
@@ -4,10 +4,10 @@ import 'package:flutter_wisetronic/models/user.dart';
import '../actions.dart'; import '../actions.dart';
final userReducer = combineReducers<User>([ final userReducer = combineReducers<User?>([
TypedReducer<User, UpdateCurrentUser>(_updateCurrentUser) TypedReducer<User?, UpdateCurrentUser>(_updateCurrentUser)
]); ]);
User _updateCurrentUser(User user, action) { User? _updateCurrentUser(User? user, action) {
return action.user; return action.user;
} }
+12 -12
View File
@@ -6,16 +6,16 @@ import '../../models/user.dart';
@immutable @immutable
class AppState { class AppState {
final BuildContext context; final BuildContext? context;
final Locale locale; final Locale? locale;
final User user; final User? user;
final String redirectRoute; final String? redirectRoute;
final List<CartInfo> cartInfos; final List<CartInfo>? cartInfos;
final LocatedAddress locatedAddress; final LocatedAddress? locatedAddress;
final String fcmToken; final String? fcmToken;
final List<int> lastVisit; final List<int>? lastVisit;
final String deviceId; final String? deviceId;
final String tableNumber; final String? tableNumber;
AppState({this.context, this.locale, this.user, this.redirectRoute, AppState({this.context, this.locale, this.user, this.redirectRoute,
this.cartInfos, this.locatedAddress, this.fcmToken, this.lastVisit, this.cartInfos, this.locatedAddress, this.fcmToken, this.lastVisit,
@@ -24,8 +24,8 @@ class AppState {
factory AppState.init() => AppState(); factory AppState.init() => AppState();
AppState copyWith({ AppState copyWith({
BuildContext context, BuildContext? context,
Locale locale}) { Locale? locale}) {
return AppState( return AppState(
context: context ?? this.context, context: context ?? this.context,
locale: locale ?? this.locale, locale: locale ?? this.locale,

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