# Урок 1. Hello World

В разделе [Платформа Workflow Technology](https://wfsys.gitbook.io/workflow-technology) мы познакомились с [архитектурой платформы](https://wfsys.gitbook.io/workflow-technology/platform-description/platform-architecture), [составом проекта](https://wfsys.gitbook.io/workflow-technology/setting-up-dev-environment/educational-project#project-structure) и настройкой взаимосвязи его компонент. [Развернули серверную и клиентскую части](https://wfsys.gitbook.io/workflow-technology/setting-up-dev-environment/manual-deployment-project) учебного проекта. И развили проект до полноценного десктопного приложения в курсе [WT. Практика (Desktop)](https://wfsys.gitbook.io/wt-practice). В статье [Добавление мобильного приложения](https://wfsys.gitbook.io/workflow-technology/setting-up-dev-environment/manual-deployment-project/adding_mobile_app) сделали все необходимое, чтобы учебный проект мог поддерживать мобильное приложение.

В этом уроке мы скачаем мобильное приложение и настроим его на работу с серверной частью учебного проекта.

Для начала добавим проект в редактор, чтобы запустив приложение на мобильном устройстве, параллельно изучать его xml-код.

## Добавление проекта в редактор

В статье [Добавление проекта](https://wfsys.gitbook.io/workflow-technology/setting-up-dev-environment/create_project#adding-project) подробно рассматривается добавление десктопного приложения в редактор Workflow XML Editor. Процесс добавление форм мобильного приложения аналогичен за исключением одного момента: в качестве типа приложения в поле **Project type** необходимо указать Mobile, чтобы редактор подхватил схему для Workflow MobileForms:

<figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2FegTLmBCTNifVkQZITaZc%2Fimage.png?alt=media&#x26;token=582c7b36-f030-4634-9136-372ebefca168" alt=""><figcaption></figcaption></figure>

Так же не забывайте добавлять серверный xml-файл к проекту, как это описано в статье [Добавление серверного XML-файла](https://wfsys.gitbook.io/workflow-technology/setting-up-dev-environment/create_project#adding-server-xml-file).&#x20;

## Скачивание приложения <a href="#downloading-app" id="downloading-app"></a>

Скачаем мобильное приложение, просканировав QR-код:

<div><figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2FUrRXxKBwdgYXmHp9X8vs%2FQR-Google%20Play.png?alt=media&#x26;token=ab79db37-e30c-4ee8-9411-85cfc25b6597" alt=""><figcaption></figcaption></figure> <figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2FpzKzyzTri2fKNGHrsTmB%2FQR-App%20Store.png?alt=media&#x26;token=e872ffca-bbe4-41d9-aafb-d6312e492f4a" alt=""><figcaption></figcaption></figure> <figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2F064rSNgG59kdL4TnqpeU%2FQR-RuStore.png?alt=media&#x26;token=569e200d-2f91-4dbb-a1b2-efb6ecc36cae" alt=""><figcaption></figcaption></figure></div>

Или перейдя по ссылке в нужный магазин приложений:

{% embed url="https://play.google.com/store/apps/details?id=com.wfsys.ws" %}

{% embed url="https://apps.apple.com/ru/app/ws/id1636824661" %}

{% embed url="https://www.rustore.ru/catalog/app/com.wfsys.ws" %}

## Первый запуск <a href="#first-launch" id="first-launch"></a>

Запустим сервер и убедимся, что он _работает на локальном IP-адресе_, а не на localhost. Иначе мобильное приложение не сможет получить к нему доступ.

Подключим мобильное устройство к сети Wi-Fi, чтобы они с сервером вместе работали в одной локальной сети. При этом устройство может запросить разрешение на подключение к другим устройствам в сети. Разрешим ему это делать.

При первом запуске нас встречает экран с полем для ввода IP-адреса и порта сервера, с которым будет взаимодействовать мобильное приложение.

По умолчанию указан адрес и порт демо-сервера:

<figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2FcXnFAj7wiPbfbFZRSHT0%2F01_Welcome_Light_iOS.png?alt=media&#x26;token=e58a1ed1-a40d-4006-be8d-44322f3cefa7" alt="" width="311"><figcaption></figcaption></figure>

Давайте укажем IP-адрес и порт сервера учебного проекта на локальной машине, как они прописаны в файле hosting.json. Например:

<figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2FZNfMVUQ9i4DmCOoici0Q%2F02_Welcome_Light_iOS.png?alt=media&#x26;token=425d5703-fe40-4b5d-a03f-7ac39f4ba7f5" alt="" width="311"><figcaption></figcaption></figure>

После нажатия на кнопку "Продолжить" мобильное приложение отправляет запрос на указанный сервер. Сервер приняв запрос, проверяет, от какого приложения он пришел, находит нужные папки с бинарниками и xml-файлами форм и отправляет их приложению на мобильное устройство.

При поиске бинарников, сервер собирает нужный путь из поля MobileBinaryPath в конфигурационном файле appsettings.json и колонки bin\_path в таблице public.mobile\_app. При поиске xml-файлов форм сервер будет собирать путь до целевой папки из поля MobileFormsFolder в конфигурационном файле appsettings.json и колонки forms\_path в таблице public.mobile\_app.

Если сервер смог распознать мобильное приложение и найти необходимы файлы, то мобильное приложение скачает свои файлы с сервера и запустит стартовую форму. Это будет означать, что подключению прошло успешно.

### Стартовый экран <a href="#start-screen" id="start-screen"></a>

В нашем случае стартовый экран уведомляет нас об успешном подключении к серверу:

<figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2FHCZzaLTKJG31oxyeVj7O%2F03_TemplateEmptyStart_Light_iOS.png?alt=media&#x26;token=8610be86-4d61-436b-9998-f8beb5a4c076" alt="" width="311"><figcaption></figcaption></figure>

{% hint style="info" %}
Если соединение с сервером не установлено, то необходимо проверить:

* правильно ли указали IP-адрес и порт сервера в настройках мобильного приложения;
* сервер должен запускаться на конкретном IP-адресе, а не на localhost;
* правильно указаны пути в полях MobileFormsFolder и MobileBinaryPath в файле appsettings.json;
* правильно указаны относительные пути в колонках forms\_path и bin\_path в таблице public.mobile\_app относительно соответствующих путей в полях MobileFormsFolder и MobileBinaryPath в файле appsettings.json;
* если сервер запущен на внутреннем IP-адресе, то мобильное устройство должно быть подключено к той же локальной сети через Wi-Fi.
{% endhint %}

Давайте перейдем в xml-файл стартового экрана (TemplateEmptyStart.xml) и для объекта ResultLabel заменим значение в тэге `<Text>` на текст "Hello World". Перезапустим приложение (с выгрузкой приложения из памяти устройства) и проверим изменения:

<figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2FdlIlY4CXtLAdIv0U7q4p%2F04_HelloWorld_Light_iOS.png?alt=media&#x26;token=3c72a644-f0e8-4d5c-8813-dd225f8f605d" alt="" width="311"><figcaption></figcaption></figure>

### Экран настроек <a href="#settings-screen" id="settings-screen"></a>

Тапнув по изображению шестеренки в верхнем правом углу, попадем на экран настроек, где можем поменять IP-адрес сервера:

<figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2Fkf0MIPnMKOMuYZpe3LL7%2F05_TemplateEmptySettings_Light_iOS.png?alt=media&#x26;token=1c455812-c60f-4aca-835e-9507dbc57918" alt="" width="311"><figcaption></figcaption></figure>

Откроем в редакторе xml-файл TemplateEmptySettings.xml и посмотрим, как он устроен и разберем пару моментов.

По кнопке сохранить приложение сохранит изменения и попробует подключиться к серверу по указанному адресу, вызвав команду [EngineConnectCommand](https://wfsys.gitbook.io/workflow-mobile-forms-syntax/workflow_mobile_forms/commands/engine_connect_command).

```xml
<Command Name="EngineConnectCommand" Type="EngineConnectCommand" Assembly="Commands">
  <ServerAddress>
    <Object Name="AddressTextBox" />
  </ServerAddress>
</Command>
```

Если подключение будет успешным, то вызовется команда [SourceFileDownloadCommand](https://wfsys.gitbook.io/workflow-mobile-forms-syntax/workflow_mobile_forms/commands/source_file_download_command) на загрузку файлов приложения с сервера. Для этого выполнится Execution:

```xml
<Execution>
  <ConditionExpression>
    <Condition Name="EngineConnectCommandOkEqualCondition" />
  </ConditionExpression>
  <Commands>
    <Command Name="SourceFileDownloadCommand" />
  </Commands>
</Execution>
```

Где условие EngineConnectCommandOkEqualCondition проверяет результат выполнения команды EngineConnectCommand:

```xml
<Condition Name="EngineConnectCommandOkEqualCondition" Type="EqualCondition" Assembly="Conditions">
  <AlwaysChange Value="True" />
  <Items>
    <Item>
      <Command Name="EngineConnectCommand" />
    </Item>
    <Item>Ok</Item>
  </Items>
</Condition>
```

Чтобы уйти с экрана настроек, можно свайпнуть по экрану слева направо, при этом сработает условие [SwipeCondition](https://wfsys.gitbook.io/workflow-mobile-forms-syntax/workflow_mobile_forms/conditions/event_condition/swipe_condition), в котором проверяется направление свайпа:

```xml
<Condition Name="ContentPanelSwipeRightCondition" Type="SwipeCondition" Assembly="Conditions">
  <Object Name="ContentPanel" />
  <Direction>Right</Direction>
</Condition>
```

По этому условию вызовется Execution на закрытие формы:

```xml
<Execution>
  <ConditionExpression>
    <Condition Name="ContentPanelSwipeRightCondition" />
  </ConditionExpression>
  <Commands>
    <Command Name="FormCloseCommand" />
  </Commands>
</Execution>
```

## Светлое и темное оформление <a href="#light-and-dark" id="light-and-dark"></a>

В файле TemplateEmptyStart.xml можете увидеть, что у объекта ContentPanel в тэге \<BackColor> по условию AppThemeDarkEqualCondition выбирается соответствующий цвет.

Условие AppThemeDarkEqualCondition проверяет выбрано ли темное оформление в настройках устройства:

```xml
<Condition Name="AppThemeDarkEqualCondition" Type="EqualCondition" Assembly="Conditions">
  <Items>
    <Item>
      <Info Type="AppTheme" />
    </Item>
    <Item>Dark</Item>
  </Items>
</Condition>
```

Поменяем в настройках устройства стиль оформления и проверим отображение экранов при светлом и темном оформлении. Не забывайте перезапускать приложение (с предварительной выгрузкой его из памяти) каждый раз, когда меняете настройки устройства.

Основной экран при разном оформлении:

<div><figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2FdlIlY4CXtLAdIv0U7q4p%2F04_HelloWorld_Light_iOS.png?alt=media&#x26;token=3c72a644-f0e8-4d5c-8813-dd225f8f605d" alt="" width="311"><figcaption></figcaption></figure> <figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2Fww1cpNoQPp3N8VO0dEV2%2F04_HelloWorld_Dark_iOS.png?alt=media&#x26;token=3cca49f9-8556-44b3-b035-e01eaf9ac037" alt="" width="311"><figcaption></figcaption></figure></div>

И экран настроек:

<div><figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2Fkf0MIPnMKOMuYZpe3LL7%2F05_TemplateEmptySettings_Light_iOS.png?alt=media&#x26;token=1c455812-c60f-4aca-835e-9507dbc57918" alt="" width="311"><figcaption></figcaption></figure> <figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2FVpiWNfE6yig2kPfiv1BT%2F05_TemplateEmptySettings_Dark_iOS.png?alt=media&#x26;token=c4beaaba-735a-4a39-a906-421be5c71a24" alt="" width="311"><figcaption></figcaption></figure></div>

В данном примере меняется только цвет фона у основной панели. Но проверяя значение элемента `<Info Type="AppTheme" />` можно заменять изображения в PictureBox, цвет и стиль текста на кнопках и многое другое.

## Итоги <a href="#results" id="results"></a>

Отлично. Мы установили мобильное приложение на устройство, рассмотрели оба его экрана и разобрали их логику. Узнали, как подстраивать дизайн приложения под светлое или темное оформление системы.

В следующем уроке будем переделывать стартовый экран и реализовывать логику авторизации пользователя в приложении.
