# flyinsono

Flyinsono client project.

## 启动科研版运行环境

```bash
dart ./scripts/build_lab.dart
```

## 还原运行环境

```bash
dart ./scripts/revert_lab.dart
```

## 配置文件说明（`.\assets\app_params.json`）

- `server_gateway` : 服务器首选地址
- `report_designer_root` : Web 端使用报告模板设计器的地址前缀
- `local_report_designer` : PC 客户端使用报告模板设计器的地址前缀
- `theme_source_root` : 主题资源地址
- `flyinsonoServers` : 服务端备选地址列表
- `external_live_player_url` : 部署在外部的 Nodeplayer 播放器地址（需要带 fis.plus）否则用不了，置空则使用内置的播放器
- `remove_logo_domains` : 需要移除 logo 的域名列表 (注意：该配置在 web\js\pre.js 下也有一份)

## 编译安卓的注意事项

- 如遇报错：`SigningConfig "release" is missing required property "storeFile".`可能是签名文件配置未设置
- 需要在项目目录下新建 `android\key.properties`，并在其中配置签名文件信息

```properties
storePassword=xxx 【密码请询问仓库管理员】
keyPassword=xxx 【密码请询问仓库管理员】
keyAlias=flyinsono
storeFile=xxx [本地密钥文件地址]
```

## 编译 Google Play 版本的 aab 产物

- 依次执行以下

```shell
:: 1. 调整 AndroidManifest.xml 配置
rename ".\android\app\src\main\AndroidManifest.xml" "AndroidManifest.temp"
rename ".\android\app\src\main\AndroidManifest.google" "AndroidManifest.xml"

:: 2. 打包 Google 商店版本（aab）
flutter build appbundle --release --dart-define=UPGRADE_METHOD=Google --build-name=2.0.4.3745 --build-number=3745

:: 3. 还原 AndroidManifest.xml 配置
rename ".\android\app\src\main\AndroidManifest.xml" "AndroidManifest.google"
rename ".\android\app\src\main\AndroidManifest.temp" "AndroidManifest.xml"
```

## Debug

```shell
# web on chrome
flutter run -d chrome --web-port=8080 --web-hostname=127.0.0.1

# iOS local project build
flutter build ios --no-codesign
```

## Build

```shell
# web release
# flutter build web --web-renderer canvaskit --dart-define=FLUTTER_WEB_CANVASKIT_URL="/canvaskit/"
flutter build web --web-renderer canvaskit

# android release
flutter build apk --release --tree-shake-icons

# iOS release
find . -name "Podfile" -execdir pod install \;
flutter build ipa --release --export-options-plist=$HOME/export_options_appstore.plist --build-name=2.0.0 --build-number=2.0.0.1234
```

## About Canvaskit

current version: 0.37.0

https://unpkg.com/canvaskit-wasm@0.31.0/bin/canvaskit.js
https://unpkg.com/canvaskit-wasm@0.31.0/bin/canvaskit.wasm

https://www.npmjs.com/package/canvaskit-wasm

## Usage

> Step 1: Create state controller file for new page

Create new file `lib/controllers/test.page.c.dart`.

Build code structure like the following sample:

```dart
import 'package:fis_common/logger/logger.dart';
import 'package:flyinsono/localizaion/localization.dart';
import 'package:flyinsono/rpc/rpc.dart';
import 'package:get/get.dart';

import 'controller.dart';

class TestPageController extends FControllerBase {
  TestPageController() {
    // handle somethings
  }

  // collect injected dependencies
  final _localization = Get.find<FI18n>();

  // define getter/setter for state fields
  var _count = 0.obs;
  int get count => _count.value;
  set count(int value) => _count.value = value;

  // define actions
  void handleIncrease() => count++;

  Future<void> hanleSubmit() async {
    this.busy = true;

    try {
      // build rpc request
      final requst = TestSubmitRequest(
        count: count,
        lang: _localization.currentBook.locale.languageCode,
      );
      // do rpc
      var result = await RpcProxy.test.submit(request);
      // handle rpc result
      if (!result.isSuccess || result.data == null) {
        print(result.data);
      } else {
        print("submit fail");
      }
    } catch (e) {
      /// write error log
      logger.e("submit test result error", e);
    }

    this.busy = false;
  }
}

```

Then export file in `lib/controllers/controller.dart`

```dart
export 'remedical.page.c.dart';
```

<br/>
<br/>

> Step 2: Create new page file

Put file in directory `lib/pages/`, such as `lib/pages/test.page.dart`.
Then input codes like:

```dart
import 'package:fis_ui/define.dart';
import 'package:fis_ui/fisapp/scaffold.dart';
import 'package:fis_ui/index.dart';
import 'package:flutter/widgets.dart';
import 'package:flyinsono/controllers/controller.dart';
import 'package:flyinsono/define.dart';

import 'page.dart';

class TestPage extends FisPage<TestPageController> {
  @override
  FWidget build(BuildContext context) {
    return FScaffold(
      body: FCenter(
        child: FColumn(
          children: [
            // define responsive content with `FObx`
            FObx(() => FText('Count: ${controller.count}')),
            FSizedBox(height: 10),
            FButton(
              child: FText("Increase"),
              // define event handler
              onPressed: controller.handleIncrease,
            ),
            FSizedBox(height: 10),
            FButton(
              child: FText("Submit"),
              // define event handler
              onPressed: controller.hanleSubmit,
            ),
            // ... // other contents
          ],
        ),
      ),
    );
  }
}

```

Then export file in `lib/pages/page.dart`

```dart
export 'test.page.dart';
```

<br/>
<br/>

> Step 3: Register page route

Open file `lib/router.dart`.

Add route name constants in class `AppRoutes`.

```
static const String Test = "/test";
```

Then file static constants `pages`, add page route into this array.

```dart
FRouteSetting(
  RouteNames.Demo.Test,
  () => TestPage(),
  binding: BindingsBuilder.put(() => TestPageController()),
),
```

<br/>
<br/>

> Step 4: Navigate to page with route name

```dart
// on current layer
router.to(RouteNames.Demo.Test, parameters: {'cc': '123'});
// replace current layer
router.replace(RouteNames.Demo.Test);
```

## 国际化注意事项

- 多语言相关的主要仓库为 i18n
- 注意：存在多处 i18n 仓库以外的多语言相关适配区域
  - 颈动脉 3D 通过给 webview 传翻译值实现多语言切换（fis_lib_measure 库中）
  - 测量项通过给后端传参实现多语言
  - 内置的直播播放器通过 assets\webview\i18n 文件夹相关代码实现多语言切换
  - 内置的往期视频播放器以及外链播放器，通过 URL 传参实现多语言切换，相关代码位于 open_web 库
