diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..d841df6 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +github: + dependabot: + updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" \ No newline at end of file diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml new file mode 100644 index 0000000..aba5d85 --- /dev/null +++ b/.github/workflows/dart.yml @@ -0,0 +1,162 @@ +# Created with package:mono_repo v6.6.0 +name: Dart CI +on: + push: + branches: + - main + - master + pull_request: + schedule: + - cron: "0 0 * * 0" +defaults: + run: + shell: bash +env: + PUB_ENVIRONMENT: bot.github +permissions: read-all + +jobs: + job_001: + name: "unit_test; Flutter 3.3.10; `flutter test`" + runs-on: ubuntu-latest + steps: + - name: Cache Pub hosted dependencies + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + with: + path: "~/.pub-cache/hosted" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.3.10;packages:packages/aurora_push_service;commands:test" + restore-keys: | + os:ubuntu-latest;pub-cache-hosted;sdk:3.3.10;packages:packages/aurora_push_service + os:ubuntu-latest;pub-cache-hosted;sdk:3.3.10 + os:ubuntu-latest;pub-cache-hosted + os:ubuntu-latest + - name: Setup Flutter SDK + uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa + with: + channel: "3.3.10" + - id: checkout + name: Checkout repository + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - id: packages_aurora_push_service_pub_upgrade + name: packages/aurora_push_service; flutter pub upgrade + run: flutter pub upgrade + if: "always() && steps.checkout.conclusion == 'success'" + working-directory: packages/aurora_push_service + - name: packages/aurora_push_service; flutter test + run: flutter test + if: "always() && steps.packages_aurora_push_service_pub_upgrade.conclusion == 'success'" + working-directory: packages/aurora_push_service + job_002: + name: "unit_test; Flutter stable; `flutter test`" + runs-on: ubuntu-latest + steps: + - name: Cache Pub hosted dependencies + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + with: + path: "~/.pub-cache/hosted" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/aurora_push_service;commands:test" + restore-keys: | + os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/aurora_push_service + os:ubuntu-latest;pub-cache-hosted;sdk:stable + os:ubuntu-latest;pub-cache-hosted + os:ubuntu-latest + - name: Setup Flutter SDK + uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa + with: + channel: stable + - id: checkout + name: Checkout repository + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - id: packages_aurora_push_service_pub_upgrade + name: packages/aurora_push_service; flutter pub upgrade + run: flutter pub upgrade + if: "always() && steps.checkout.conclusion == 'success'" + working-directory: packages/aurora_push_service + - name: packages/aurora_push_service; flutter test + run: flutter test + if: "always() && steps.packages_aurora_push_service_pub_upgrade.conclusion == 'success'" + working-directory: packages/aurora_push_service + job_003: + name: "cron; Flutter 3.3.10; `flutter test`" + runs-on: ubuntu-latest + if: "github.event_name == 'schedule'" + steps: + - name: Cache Pub hosted dependencies + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + with: + path: "~/.pub-cache/hosted" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.3.10;packages:packages/aurora_push_service;commands:test" + restore-keys: | + os:ubuntu-latest;pub-cache-hosted;sdk:3.3.10;packages:packages/aurora_push_service + os:ubuntu-latest;pub-cache-hosted;sdk:3.3.10 + os:ubuntu-latest;pub-cache-hosted + os:ubuntu-latest + - name: Setup Flutter SDK + uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa + with: + channel: "3.3.10" + - id: checkout + name: Checkout repository + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - id: packages_aurora_push_service_pub_upgrade + name: packages/aurora_push_service; flutter pub upgrade + run: flutter pub upgrade + if: "always() && steps.checkout.conclusion == 'success'" + working-directory: packages/aurora_push_service + - name: packages/aurora_push_service; flutter test + run: flutter test + if: "always() && steps.packages_aurora_push_service_pub_upgrade.conclusion == 'success'" + working-directory: packages/aurora_push_service + needs: + - job_001 + - job_002 + job_004: + name: "cron; Flutter stable; `flutter test`" + runs-on: ubuntu-latest + if: "github.event_name == 'schedule'" + steps: + - name: Cache Pub hosted dependencies + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + with: + path: "~/.pub-cache/hosted" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/aurora_push_service;commands:test" + restore-keys: | + os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/aurora_push_service + os:ubuntu-latest;pub-cache-hosted;sdk:stable + os:ubuntu-latest;pub-cache-hosted + os:ubuntu-latest + - name: Setup Flutter SDK + uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa + with: + channel: stable + - id: checkout + name: Checkout repository + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - id: packages_aurora_push_service_pub_upgrade + name: packages/aurora_push_service; flutter pub upgrade + run: flutter pub upgrade + if: "always() && steps.checkout.conclusion == 'success'" + working-directory: packages/aurora_push_service + - name: packages/aurora_push_service; flutter test + run: flutter test + if: "always() && steps.packages_aurora_push_service_pub_upgrade.conclusion == 'success'" + working-directory: packages/aurora_push_service + needs: + - job_001 + - job_002 + job_005: + name: Notify failure + runs-on: ubuntu-latest + if: failure() + steps: + - run: | + curl -H "Content-Type: application/json" -X POST -d \ + "{'text':'Build failed! ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}'}" \ + "${CHAT_WEBHOOK_URL}" + env: + CHAT_WEBHOOK_URL: "${{ secrets.CHAT_WEBHOOK_URL }}" + needs: + - job_001 + - job_002 + - job_003 + - job_004 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..8a8f93e --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,178 @@ +# Created with package:mono_repo v6.6.0 +name: Dart Lint CI +on: + push: + branches: + - main + - master + pull_request: + schedule: + - cron: "0 0 * * 0" +defaults: + run: + shell: bash +env: + PUB_ENVIRONMENT: bot.github +permissions: read-all + +jobs: + job_001: + name: mono_repo self validate + runs-on: ubuntu-latest + steps: + - name: Cache Pub hosted dependencies + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + with: + path: "~/.pub-cache/hosted" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable" + restore-keys: | + os:ubuntu-latest;pub-cache-hosted + os:ubuntu-latest + - name: Setup Dart SDK + uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + with: + sdk: stable + - id: checkout + name: Checkout repository + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - name: mono_repo self validate + run: dart pub global activate mono_repo 6.6.0 + - name: mono_repo self validate + run: dart pub global run mono_repo generate --validate + job_002: + name: "analyze; Flutter 3.3.10; `dart format --output=none --set-exit-if-changed .`" + runs-on: ubuntu-latest + steps: + - name: Cache Pub hosted dependencies + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + with: + path: "~/.pub-cache/hosted" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.3.10;packages:packages/aurora_push_service;commands:format" + restore-keys: | + os:ubuntu-latest;pub-cache-hosted;sdk:3.3.10;packages:packages/aurora_push_service + os:ubuntu-latest;pub-cache-hosted;sdk:3.3.10 + os:ubuntu-latest;pub-cache-hosted + os:ubuntu-latest + - name: Setup Flutter SDK + uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa + with: + channel: "3.3.10" + - id: checkout + name: Checkout repository + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - id: packages_aurora_push_service_pub_upgrade + name: packages/aurora_push_service; flutter pub upgrade + run: flutter pub upgrade + if: "always() && steps.checkout.conclusion == 'success'" + working-directory: packages/aurora_push_service + - name: "packages/aurora_push_service; dart format --output=none --set-exit-if-changed ." + run: "dart format --output=none --set-exit-if-changed ." + if: "always() && steps.packages_aurora_push_service_pub_upgrade.conclusion == 'success'" + working-directory: packages/aurora_push_service + job_003: + name: "analyze; Flutter 3.3.10; `flutter analyze`" + runs-on: ubuntu-latest + steps: + - name: Cache Pub hosted dependencies + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + with: + path: "~/.pub-cache/hosted" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.3.10;packages:packages/aurora_push_service;commands:analyze" + restore-keys: | + os:ubuntu-latest;pub-cache-hosted;sdk:3.3.10;packages:packages/aurora_push_service + os:ubuntu-latest;pub-cache-hosted;sdk:3.3.10 + os:ubuntu-latest;pub-cache-hosted + os:ubuntu-latest + - name: Setup Flutter SDK + uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa + with: + channel: "3.3.10" + - id: checkout + name: Checkout repository + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - id: packages_aurora_push_service_pub_upgrade + name: packages/aurora_push_service; flutter pub upgrade + run: flutter pub upgrade + if: "always() && steps.checkout.conclusion == 'success'" + working-directory: packages/aurora_push_service + - name: packages/aurora_push_service; flutter analyze + run: flutter analyze + if: "always() && steps.packages_aurora_push_service_pub_upgrade.conclusion == 'success'" + working-directory: packages/aurora_push_service + job_004: + name: "analyze; Flutter stable; `dart format --output=none --set-exit-if-changed .`" + runs-on: ubuntu-latest + steps: + - name: Cache Pub hosted dependencies + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + with: + path: "~/.pub-cache/hosted" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/aurora_push_service;commands:format" + restore-keys: | + os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/aurora_push_service + os:ubuntu-latest;pub-cache-hosted;sdk:stable + os:ubuntu-latest;pub-cache-hosted + os:ubuntu-latest + - name: Setup Flutter SDK + uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa + with: + channel: stable + - id: checkout + name: Checkout repository + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - id: packages_aurora_push_service_pub_upgrade + name: packages/aurora_push_service; flutter pub upgrade + run: flutter pub upgrade + if: "always() && steps.checkout.conclusion == 'success'" + working-directory: packages/aurora_push_service + - name: "packages/aurora_push_service; dart format --output=none --set-exit-if-changed ." + run: "dart format --output=none --set-exit-if-changed ." + if: "always() && steps.packages_aurora_push_service_pub_upgrade.conclusion == 'success'" + working-directory: packages/aurora_push_service + job_005: + name: "analyze; Flutter stable; `flutter analyze`" + runs-on: ubuntu-latest + steps: + - name: Cache Pub hosted dependencies + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + with: + path: "~/.pub-cache/hosted" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/aurora_push_service;commands:analyze" + restore-keys: | + os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/aurora_push_service + os:ubuntu-latest;pub-cache-hosted;sdk:stable + os:ubuntu-latest;pub-cache-hosted + os:ubuntu-latest + - name: Setup Flutter SDK + uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa + with: + channel: stable + - id: checkout + name: Checkout repository + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - id: packages_aurora_push_service_pub_upgrade + name: packages/aurora_push_service; flutter pub upgrade + run: flutter pub upgrade + if: "always() && steps.checkout.conclusion == 'success'" + working-directory: packages/aurora_push_service + - name: packages/aurora_push_service; flutter analyze + run: flutter analyze + if: "always() && steps.packages_aurora_push_service_pub_upgrade.conclusion == 'success'" + working-directory: packages/aurora_push_service + job_006: + name: Notify failure + runs-on: ubuntu-latest + if: failure() + steps: + - run: | + curl -H "Content-Type: application/json" -X POST -d \ + "{'text':'Build failed! ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}'}" \ + "${CHAT_WEBHOOK_URL}" + env: + CHAT_WEBHOOK_URL: "${{ secrets.CHAT_WEBHOOK_URL }}" + needs: + - job_001 + - job_002 + - job_003 + - job_004 + - job_005 diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..2c3a2dc --- /dev/null +++ b/AUTHORS @@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the project. Names should be added to the list like so: +# +# Name/Organization + +Friflex LLC \ No newline at end of file diff --git a/README.md b/README.md index 065f0fb..b324c8e 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# aurora_flutter \ No newline at end of file +# Aurora Flutter diff --git a/mono_repo.yaml b/mono_repo.yaml new file mode 100644 index 0000000..27c178c --- /dev/null +++ b/mono_repo.yaml @@ -0,0 +1,83 @@ +# Enabled GitHub actions - https://docs.github.com/actions +# If you have no configuration, you can set the value to `true` or just leave it +# empty. +github: + # Specify the `on` key to configure triggering events. + # See https://docs.github.com/actions/reference/workflow-syntax-for-github-actions#on + # The default values is + # on: + # push: + # branches: + # - main + # - master + # pull_request: + + # Setting just `cron` is a shortcut to keep the defaults for `push` and + # `pull_request` while adding a single `schedule` entry. + # `on` and `cron` cannot both be set. + cron: '0 0 * * 0' # “At 00:00 (UTC) on Sunday.” + + # Specify additional environment variables accessible to all jobs +# env: +# FOO: BAR + + # You can group stages into individual workflows + # + # Any stages that are omitted here are put in a default workflow + # named `dart.yml`. + workflows: + # The key here is the name of the file - .github/workflows/lint.yml + lint: + # This populates `name` in the workflow + name: Dart Lint CI + # These are the stages that are populated in the workflow file + stages: + - analyze + + # You can add custom github actions configurations to run after completion + # of all other jobs here. This accepts normal github job config except that + # the `needs` config is filled in for you, and you aren't allowed to pass it. + on_completion: + # Example job that pings a web hook url stored in a github secret with a + # json payload linking to the failed run. + - name: "Notify failure" + runs-on: ubuntu-latest + # By default this job will only run if all dependent jobs are successful, + # but we want to run in the failure case for this purpose. + if: failure() + steps: + - run: > + curl -H "Content-Type: application/json" -X POST -d \ + "{'text':'Build failed! ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}'}" \ + "${CHAT_WEBHOOK_URL}" + env: + CHAT_WEBHOOK_URL: ${{ secrets.CHAT_WEBHOOK_URL }} + + # You can customize stage ordering as well as make certain stages be + # conditional here, this is supported for all CI providers. The `if` + # condition should use the appropriate syntax for the provider it is being + # configured for. + stages: + - name: cron + # Only run this stage for scheduled cron jobs + if: github.event_name == 'schedule' + +# Adds a job that runs `mono_repo generate --validate` to check that everything +# is up to date. You can specify the value as just `true` or give a `stage` +# you'd like this job to run in. +self_validate: analyze + +# Use this key to merge stages across packages to create fewer jobs +merge_stages: + - analyze + +# When using `test_with_coverage`, this setting configures the service that +# results are uploaded to. +# Note: you can configure both options, but this would be unusual. +# Note: you can configure this key with no values, to just generate the files +# locally. This may be to enable other, custom processing. +coverage_service: + # https://coveralls.io/ - the default + - coveralls + # https://codecov.io/ – the other option + - codecov \ No newline at end of file diff --git a/packages/aurora_push_service/.gitignore b/packages/aurora_push_service/.gitignore new file mode 100644 index 0000000..96486fd --- /dev/null +++ b/packages/aurora_push_service/.gitignore @@ -0,0 +1,30 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.packages +build/ diff --git a/packages/aurora_push_service/.metadata b/packages/aurora_push_service/.metadata new file mode 100644 index 0000000..641645c --- /dev/null +++ b/packages/aurora_push_service/.metadata @@ -0,0 +1,30 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled. + +version: + revision: 135454af32477f815a7525073027a3ff9eff1bfd + channel: aurora + +project_type: plugin + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 135454af32477f815a7525073027a3ff9eff1bfd + base_revision: 135454af32477f815a7525073027a3ff9eff1bfd + - platform: aurora + create_revision: 135454af32477f815a7525073027a3ff9eff1bfd + base_revision: 135454af32477f815a7525073027a3ff9eff1bfd + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/aurora_push_service/AUTHORS b/packages/aurora_push_service/AUTHORS new file mode 100644 index 0000000..2c3a2dc --- /dev/null +++ b/packages/aurora_push_service/AUTHORS @@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the project. Names should be added to the list like so: +# +# Name/Organization + +Friflex LLC \ No newline at end of file diff --git a/packages/aurora_push_service/CHANGELOG.md b/packages/aurora_push_service/CHANGELOG.md new file mode 100644 index 0000000..5b854c5 --- /dev/null +++ b/packages/aurora_push_service/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.2.0 + +* Initial Open Source release. diff --git a/packages/aurora_push_service/LICENSE b/packages/aurora_push_service/LICENSE new file mode 100644 index 0000000..0fe71cb --- /dev/null +++ b/packages/aurora_push_service/LICENSE @@ -0,0 +1,11 @@ +Copyright 2023 Friflex LLC + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/packages/aurora_push_service/README.md b/packages/aurora_push_service/README.md new file mode 100644 index 0000000..2244dee --- /dev/null +++ b/packages/aurora_push_service/README.md @@ -0,0 +1,15 @@ +# aurora_push_service + + + +## Getting Started + +This project is a starting point for a Flutter +[plug-in package](https://flutter.dev/developing-packages/), +a specialized package that includes platform-specific implementation code for +Android and/or iOS. + +For help getting started with Flutter development, view the +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. + diff --git a/packages/aurora_push_service/analysis_options.yaml b/packages/aurora_push_service/analysis_options.yaml new file mode 100644 index 0000000..a5744c1 --- /dev/null +++ b/packages/aurora_push_service/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/packages/aurora_push_service/aurora/CMakeLists.txt b/packages/aurora_push_service/aurora/CMakeLists.txt new file mode 100644 index 0000000..1014380 --- /dev/null +++ b/packages/aurora_push_service/aurora/CMakeLists.txt @@ -0,0 +1,46 @@ +cmake_minimum_required(VERSION 3.10) + +set(PROJECT_NAME aurora_push) +set(PLUGIN_NAME aurora_push_platform_plugin) + +project(${PROJECT_NAME} LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-psabi") +set(CMAKE_CXX_FLAGS_RELEASE "-O3") + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +set(APP_ID_PATH /usr/share/${PROJECT_NAME}) +set(APP_ID_FILE applicationidz) + +add_definitions(-DDBUS_SERVICE="ru.auroraos.PushReceiver") +add_definitions(-DDBUS_PATH="/ru/auroraos/PushReceiver") +add_definitions(-DDBUS_INTERFACE="ru.auroraos.PushReceiver") +add_definitions(-DAPP_ID_FILE_PATH="${APP_ID_PATH}/${APP_ID_FILE}") + +find_package(PkgConfig REQUIRED) +find_package(Qt5 COMPONENTS Core Network DBus REQUIRED) + +pkg_check_modules(FlutterEmbedder REQUIRED IMPORTED_TARGET flutter-embedder) +pkg_check_modules(NemoNotifications-Qt5 REQUIRED IMPORTED_TARGET nemonotifications-qt5) +pkg_check_modules(PushClient REQUIRED IMPORTED_TARGET pushclient) + +add_library(${PLUGIN_NAME} SHARED + include/aurora_push/plugincontroller.cpp + include/aurora_push/pluginservice.cpp + aurora_push_plugin.cpp) + +set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) + +target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::FlutterEmbedder) +target_link_libraries(${PLUGIN_NAME} PUBLIC Qt5::Core Qt5::Network Qt5::DBus) +target_link_libraries(${PLUGIN_NAME} PUBLIC PkgConfig::NemoNotifications-Qt5) +target_link_libraries(${PLUGIN_NAME} PUBLIC PkgConfig::PushClient) + +target_include_directories(${PLUGIN_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_compile_definitions(${PLUGIN_NAME} PRIVATE PLUGIN_IMPL) diff --git a/packages/aurora_push_service/aurora/aurora_push_plugin.cpp b/packages/aurora_push_service/aurora/aurora_push_plugin.cpp new file mode 100644 index 0000000..7720ceb --- /dev/null +++ b/packages/aurora_push_service/aurora/aurora_push_plugin.cpp @@ -0,0 +1,96 @@ +/******************************************************************************* +** Copyright (c) 2023, Friflex LLC. Please see the AUTHORS file +** for details. Use of this source code is governed by a +** BSD-style license that can be found in the LICENSE file. +*******************************************************************************/ + + +//****************************************************************************** +//****************************************************************************** + +#include "aurora_push/plugincontroller.h" +#include "aurora_push/pluginservice.h" + +#include +#include + +#include +#include + +//****************************************************************************** +//****************************************************************************** +class AuroraPushPlugin::impl +{ + friend class AuroraPushPlugin; + + std::shared_ptr m_controller; + std::shared_ptr m_service; +}; + +//****************************************************************************** +//****************************************************************************** +AuroraPushPlugin::AuroraPushPlugin() + : PluginInterface() + , m_p(new impl) +{ + qDebug() << Q_FUNC_INFO; +} + +//****************************************************************************** +//****************************************************************************** +void AuroraPushPlugin::RegisterWithRegistrar(PluginRegistrar ®istrar) +{ + registrar.RegisterMethodChannel("friflex/aurora_push", + MethodCodecType::Standard, + [this](const MethodCall &call) + { + this->onMethodCall(call); + }); +} + +//****************************************************************************** +//****************************************************************************** +void AuroraPushPlugin::onMethodCall(const MethodCall & call) +{ + const auto &method = call.GetMethod(); + + if (method == "Messaging#init") + { + init(call); + return; + } + + unimplemented(call); +} + +//****************************************************************************** +//****************************************************************************** +void AuroraPushPlugin::init(const MethodCall & call) +{ + qDebug() << Q_FUNC_INFO; + + m_p->m_service.reset(new PluginService(qApp)); + m_p->m_controller.reset(new PluginController(qApp)); + + QObject::connect(m_p->m_service.get(), &PluginService::guiRequested, + m_p->m_controller.get(), &PluginController::showGui); + + const std::string applicationId = call.GetArgument("applicationId"); + if (applicationId.empty()) + { + call.SendErrorResponse("-1", "Empty application ID", nullptr); + return; + } + + m_p->m_controller->setApplicationId(QString::fromStdString(applicationId)); + + call.SendSuccessResponse(nullptr); +} + +//****************************************************************************** +//****************************************************************************** +void AuroraPushPlugin::unimplemented(const MethodCall &call) +{ + // TODO(mozerrr): заменить на void SendErrorResponse(const std::string &code, const std::string &message, const Encodable &details) const; + call.SendSuccessResponse(nullptr); +} diff --git a/packages/aurora_push_service/aurora/include/aurora_push/aurora_push_plugin.h b/packages/aurora_push_service/aurora/include/aurora_push/aurora_push_plugin.h new file mode 100644 index 0000000..4bfbfce --- /dev/null +++ b/packages/aurora_push_service/aurora/include/aurora_push/aurora_push_plugin.h @@ -0,0 +1,40 @@ +/******************************************************************************* +** Copyright (c) 2023, Friflex LLC. Please see the AUTHORS file +** for details. Use of this source code is governed by a +** BSD-style license that can be found in the LICENSE file. +*******************************************************************************/ + +//****************************************************************************** +//****************************************************************************** + +#ifndef FLUTTER_PLUGIN_AURORA_PUSH_PLUGIN_H +#define FLUTTER_PLUGIN_AURORA_PUSH_PLUGIN_H + +#include +#include + +#include + +#include + +//****************************************************************************** +//****************************************************************************** +class PLUGIN_EXPORT AuroraPushPlugin final : public PluginInterface +{ +public: + AuroraPushPlugin(); + +public: + void RegisterWithRegistrar(PluginRegistrar ®istrar) override; + +private: + void onMethodCall(const MethodCall &call); + void init(const MethodCall &call); + void unimplemented(const MethodCall &call); + +private: + class impl; + std::shared_ptr m_p; +}; + +#endif /* FLUTTER_PLUGIN_AURORA_PUSH_PLUGIN_H */ diff --git a/packages/aurora_push_service/aurora/include/aurora_push/globals.h b/packages/aurora_push_service/aurora/include/aurora_push/globals.h new file mode 100644 index 0000000..65094ea --- /dev/null +++ b/packages/aurora_push_service/aurora/include/aurora_push/globals.h @@ -0,0 +1,16 @@ +/******************************************************************************* +** Copyright (c) 2023, Friflex LLC. Please see the AUTHORS file +** for details. Use of this source code is governed by a +** BSD-style license that can be found in the LICENSE file. +*******************************************************************************/ + +#ifndef FLUTTER_PLUGIN_AURORA_PUSH_PLUGIN_GLOBALS_H +#define FLUTTER_PLUGIN_AURORA_PUSH_PLUGIN_GLOBALS_H + +#ifdef PLUGIN_IMPL +#define PLUGIN_EXPORT __attribute__((visibility("default"))) +#else +#define PLUGIN_EXPORT +#endif + +#endif /* FLUTTER_PLUGIN_AURORA_PUSH_PLUGIN_GLOBALS_H */ diff --git a/packages/aurora_push_service/aurora/include/aurora_push/plugincontroller.cpp b/packages/aurora_push_service/aurora/include/aurora_push/plugincontroller.cpp new file mode 100644 index 0000000..d7bdb89 --- /dev/null +++ b/packages/aurora_push_service/aurora/include/aurora_push/plugincontroller.cpp @@ -0,0 +1,243 @@ +/******************************************************************************* +** +** Copyright (C) 2021-2022 Open Mobile Platform LLC. +** Contact: https://community.omprussia.ru/open-source +** +** This file is part of the Push Receiver project. +** +** Redistribution and use in source and binary forms, +** with or without modification, are permitted provided +** that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer +** in the documentation and/or other materials provided with the distribution. +** * Neither the name of the copyright holder nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +** OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; +** OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) +** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +** EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +*******************************************************************************/ + +/******************************************************************************* +** Copyright (c) 2023, Friflex LLC. Please see the AUTHORS file +** for details. Use of this source code is governed by a +** BSD-style license that can be found in the LICENSE file. +*******************************************************************************/ + +#include "plugincontroller.h" +#include "pluginservice.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +// #include +#include + +#include +#include + +//****************************************************************************** +//****************************************************************************** +class PluginController::impl +{ + friend class PluginController; + + // owner + PluginController * m_o; + + // + Aurora::PushNotifications::Client * m_notificationsClient; + + // + QString m_registrationId; + + // + MethodChannel m_notificationsChannel; + + impl(PluginController * owner); +}; + +//****************************************************************************** +//****************************************************************************** +PluginController::impl::impl(PluginController * owner) + : m_o(owner) + , m_notificationsClient(new Aurora::PushNotifications::Client(owner)) + , m_notificationsChannel("friflex/aurora_push", MethodCodecType::Standard) +{ + +} + +//****************************************************************************** +//****************************************************************************** +PluginController::PluginController(QObject *parent) + : QObject(parent) + , m_p(new impl(this)) +{ + // Вызывается после обработки пуша. + // Узнать что делать с этим дальше. + connect(m_p->m_notificationsClient, + &Aurora::PushNotifications::Client::clientInactive, + [this]() + { + qDebug() << "Aurora::PushNotifications::Client::clientInactive"; + // qApp->quit(); + }); + + // not available если не сконфигурирован демон или mdm заблокировал пуши (?) + connect(m_p->m_notificationsClient, + &Aurora::PushNotifications::Client::pushSystemReadinessChanged, + [this](bool status) + { + qWarning() << "Push system is" << (status ? "available" : "not available"); + m_p->m_notificationsChannel.InvokeMethod("Messaging#onReadinessChanged", Encodable(status)); + }); + + connect(m_p->m_notificationsClient, + &Aurora::PushNotifications::Client::registrationId, + this, + &PluginController::_setRegistrationId); + + // TODO(mozerrr): уточнить когда возникает + connect(m_p->m_notificationsClient, + &Aurora::PushNotifications::Client::registrationError, + [this]() + { + qWarning() << "Push system have problems with registrationId"; + m_p->m_notificationsChannel.InvokeMethod("Messaging#onRegistrationError", Encodable("Push system have problems with registrationId")); + }); + + // Обработка пушей + connect(m_p->m_notificationsClient, + &Aurora::PushNotifications::Client::notifications, + [this](const Aurora::PushNotifications::PushList & pushList) + { + for (const auto & push : pushList) + { + QJsonDocument jsonDocument = QJsonDocument::fromJson(push.data.toUtf8()); + QString notifyType = jsonDocument.object().value("mtype").toString(); + + if (notifyType == QStringLiteral("action")) + { + continue; + } + + static QVariant defaultAction = Notification::remoteAction(QStringLiteral("default"), tr("Open app"), + PluginService::notifyDBusService(), + PluginService::notifyDBusPath(), + PluginService::notifyDBusIface(), + PluginService::notifyDBusMethod()); + + qDebug() << Q_FUNC_INFO << push.title << push.message; + + // emit pushMessageReceived(push); + + Encodable::Map pushParams; + pushParams.emplace(std::make_pair(Encodable("title"), Encodable(push.title.toStdString()))); + pushParams.emplace(std::make_pair(Encodable("message"), Encodable(push.message.toStdString()))); + + m_p->m_notificationsChannel.InvokeMethod("Messaging#onMessage", pushParams); + } + }); +} + +//****************************************************************************** +//****************************************************************************** +QString PluginController::applicationId() const +{ + return m_p->m_notificationsClient->applicationId(); +} + +//****************************************************************************** +//****************************************************************************** +void PluginController::setApplicationId(const QString & applicationId) +{ + qDebug() << Q_FUNC_INFO << applicationId; + + if (applicationId.isEmpty()) + { + qWarning() << "Empty application id, ignored"; + return; + } + + if (m_p->m_notificationsClient->applicationId() == applicationId) + { + return; + } + + m_p->m_notificationsClient->setApplicationId(applicationId); + m_p->m_notificationsClient->registrate(); + + emit applicationIdChanged(applicationId); +} + +//****************************************************************************** +//****************************************************************************** +QString PluginController::registrationId() const +{ + return m_p->m_registrationId; +} + +//****************************************************************************** +//****************************************************************************** +void PluginController::showGui() +{ + qDebug() << Q_FUNC_INFO; + + // TODO show gui? + + // if (m_view) + // { + // m_view->raise(); + // m_view->showFullScreen(); + // } + // else + // { + // m_view = Aurora::Application::createView(); + // m_view->rootContext()->setContextProperty(QStringLiteral("PluginController"), this); + // somehow show flutter app + // m_view->setSource(Aurora::Application::pathTo(QStringLiteral("qml/PushReceiver.qml"))); + // m_view->show(); + // } +} + +//****************************************************************************** +//****************************************************************************** +void PluginController::_setRegistrationId(const QString ®istrationId) +{ + qDebug() << Q_FUNC_INFO << registrationId; + + if (registrationId == m_p->m_registrationId) + { + return; + } + + m_p->m_registrationId = registrationId; + + emit registrationIdChanged(registrationId); + + m_p->m_notificationsChannel.InvokeMethod("Messaging#applicationRegistered", Encodable(registrationId.toStdString())); +} diff --git a/packages/aurora_push_service/aurora/include/aurora_push/plugincontroller.h b/packages/aurora_push_service/aurora/include/aurora_push/plugincontroller.h new file mode 100644 index 0000000..8bf8841 --- /dev/null +++ b/packages/aurora_push_service/aurora/include/aurora_push/plugincontroller.h @@ -0,0 +1,87 @@ +/******************************************************************************* +** +** Copyright (C) 2021-2022 Open Mobile Platform LLC. +** Contact: https://community.omprussia.ru/open-source +** +** This file is part of the Push Receiver project. +** +** Redistribution and use in source and binary forms, +** with or without modification, are permitted provided +** that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer +** in the documentation and/or other materials provided with the distribution. +** * Neither the name of the copyright holder nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +** OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; +** OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) +** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +** EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +*******************************************************************************/ + +/******************************************************************************* +** Copyright (c) 2023, Friflex LLC. Please see the AUTHORS file +** for details. Use of this source code is governed by a +** BSD-style license that can be found in the LICENSE file. +*******************************************************************************/ + + +#ifndef APPLICATIONCONTROLLER_H +#define APPLICATIONCONTROLLER_H + +#include + +#include + +#include + +#include + +//****************************************************************************** +//****************************************************************************** +class PluginController : public QObject +{ + Q_OBJECT + +public: + explicit PluginController(QObject *parent = nullptr); + + QString applicationId() const; + void setApplicationId(const QString & applicationId); + + QString registrationId() const; + +signals: + void applicationIdChanged(const QString &applicationId); + void registrationIdChanged(const QString ®istrationId); + void pushMessageReceived(const Aurora::PushNotifications::Push & push); + +public slots: + void showGui(); + +private slots: + void _setRegistrationId(const QString ®istrationId); + +private: + class impl; + std::shared_ptr m_p; +}; + +#endif // APPLICATIONCONTROLLER_H diff --git a/packages/aurora_push_service/aurora/include/aurora_push/pluginservice.cpp b/packages/aurora_push_service/aurora/include/aurora_push/pluginservice.cpp new file mode 100644 index 0000000..8cb4636 --- /dev/null +++ b/packages/aurora_push_service/aurora/include/aurora_push/pluginservice.cpp @@ -0,0 +1,165 @@ +/******************************************************************************* +** +** Copyright (C) 2021-2022 Open Mobile Platform LLC. +** Contact: https://community.omprussia.ru/open-source +** +** This file is part of the Push Receiver project. +** +** Redistribution and use in source and binary forms, +** with or without modification, are permitted provided +** that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer +** in the documentation and/or other materials provided with the distribution. +** * Neither the name of the copyright holder nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +** OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; +** OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) +** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +** EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +*******************************************************************************/ + +/******************************************************************************* +** Copyright (c) 2023, Friflex LLC. Please see the AUTHORS file +** for details. Use of this source code is governed by a +** BSD-style license that can be found in the LICENSE file. +*******************************************************************************/ + +#include "pluginservice.h" + +#include +#include +#include +#include +#include + +//****************************************************************************** +//****************************************************************************** +const QString dbusServiceStr = QStringLiteral(DBUS_SERVICE); +const QString dbusPathStr = QStringLiteral(DBUS_PATH); +const QString dbusIfaceStr = QStringLiteral(DBUS_INTERFACE); +const QString dbusMethodStr = QStringLiteral("handleApplicationArgs"); +const QString dbusMethodAppWakeUp = QStringLiteral("handleApplicationWakeUp"); + +//****************************************************************************** +//****************************************************************************** +PluginService::PluginService(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + qDebug() << "PluginService create"; + + setAutoRelaySignals(true); + + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.registerObject(dbusPathStr, this, QDBusConnection::ExportAllSlots); + if (!isRegistered()) + { + bool success = dbus.registerService(dbusServiceStr); + if (!success) + { + // Когда здесь может произойти ошибка? + // TODO emit error? + // qApp->quit(); + qDebug() << Q_FUNC_INFO << "dbus.registerService failed"; + } + } +} + +//****************************************************************************** +//****************************************************************************** +PluginService::~PluginService() +{ + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.unregisterObject(dbusPathStr); + dbus.unregisterService(dbusServiceStr); +} + +//****************************************************************************** +//****************************************************************************** +bool PluginService::isRegistered() +{ + return QDBusConnection::sessionBus().interface()->isServiceRegistered(dbusServiceStr); +} + +//****************************************************************************** +//****************************************************************************** +QString PluginService::notifyDBusService() +{ + return dbusServiceStr; +} + +//****************************************************************************** +//****************************************************************************** +QString PluginService::notifyDBusPath() +{ + return dbusPathStr; +} + +//****************************************************************************** +//****************************************************************************** +QString PluginService::notifyDBusIface() +{ + return dbusIfaceStr; +} + +//****************************************************************************** +//****************************************************************************** +QString PluginService::notifyDBusMethod() +{ + return dbusMethodAppWakeUp; +} + +//****************************************************************************** +//****************************************************************************** +int PluginService::updateApplicationArgs(const QStringList &arguments) +{ + qDebug() << Q_FUNC_INFO; + + QDBusMessage message = QDBusMessage::createMethodCall(dbusServiceStr, dbusPathStr, dbusIfaceStr, dbusMethodStr); + message.setArguments(QList() << arguments); + QDBusMessage reply = QDBusConnection::sessionBus().call(message); + + return 0; +} + +//****************************************************************************** +// уточнить статус поддержки +//****************************************************************************** +void PluginService::handleApplicationArgs(const QStringList &arguments) +{ + qDebug() << Q_FUNC_INFO; + + if (arguments.indexOf(QStringLiteral("/no-gui")) != -1) + { + return; + } + + // somehow show flutter app + emit guiRequested(); +} + +//****************************************************************************** +// уточнить статус поддержки +//****************************************************************************** +void PluginService::handleApplicationWakeUp() +{ + // somehow show flutter app + emit guiRequested(); +} diff --git a/packages/aurora_push_service/aurora/include/aurora_push/pluginservice.h b/packages/aurora_push_service/aurora/include/aurora_push/pluginservice.h new file mode 100644 index 0000000..2cf2e03 --- /dev/null +++ b/packages/aurora_push_service/aurora/include/aurora_push/pluginservice.h @@ -0,0 +1,80 @@ +/******************************************************************************* +** +** Copyright (C) 2021-2022 Open Mobile Platform LLC. +** Contact: https://community.omprussia.ru/open-source +** +** This file is part of the Push Receiver project. +** +** Redistribution and use in source and binary forms, +** with or without modification, are permitted provided +** that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer +** in the documentation and/or other materials provided with the distribution. +** * Neither the name of the copyright holder nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +** OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; +** OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) +** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +** EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +*******************************************************************************/ + +/******************************************************************************* +** Copyright (c) 2023, Friflex LLC. Please see the AUTHORS file +** for details. Use of this source code is governed by a +** BSD-style license that can be found in the LICENSE file. +*******************************************************************************/ + + +#ifndef APPLICATIONSERVICE_H +#define APPLICATIONSERVICE_H + +#include + +//****************************************************************************** +//****************************************************************************** +class PluginService : public QDBusAbstractAdaptor +{ + Q_OBJECT + + Q_CLASSINFO("D-Bus Interface", DBUS_INTERFACE) + +public: + explicit PluginService(QObject *parent = nullptr); + ~PluginService() override; + + static bool isRegistered(); + + static QString notifyDBusService(); + static QString notifyDBusPath(); + static QString notifyDBusIface(); + static QString notifyDBusMethod(); + + static int updateApplicationArgs(const QStringList &arguments); + +signals: + void guiRequested(); + +public slots: + void handleApplicationArgs(const QStringList &arguments); + void handleApplicationWakeUp(); +}; + +#endif // APPLICATIONSERVICE_H diff --git a/packages/aurora_push_service/example/.gitignore b/packages/aurora_push_service/example/.gitignore new file mode 100644 index 0000000..4e67902 --- /dev/null +++ b/packages/aurora_push_service/example/.gitignore @@ -0,0 +1,48 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ +pubspec.lock + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build.md artifacts here +/android/app/debug +/android/app/profile +/android/app/release + +# Aurora generated +/aurora/flutter diff --git a/packages/aurora_push_service/example/README.md b/packages/aurora_push_service/example/README.md new file mode 100644 index 0000000..3caa04e --- /dev/null +++ b/packages/aurora_push_service/example/README.md @@ -0,0 +1,16 @@ +# aurora_push_example + +Demonstrates how to use the aurora_push plugin. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/packages/aurora_push_service/example/analysis_options.yaml b/packages/aurora_push_service/example/analysis_options.yaml new file mode 100644 index 0000000..61b6c4d --- /dev/null +++ b/packages/aurora_push_service/example/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/packages/aurora_push_service/example/aurora/.gitignore b/packages/aurora_push_service/example/aurora/.gitignore new file mode 100644 index 0000000..d3896c9 --- /dev/null +++ b/packages/aurora_push_service/example/aurora/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/packages/aurora_push_service/example/aurora/CMakeLists.txt b/packages/aurora_push_service/example/aurora/CMakeLists.txt new file mode 100644 index 0000000..8f7212c --- /dev/null +++ b/packages/aurora_push_service/example/aurora/CMakeLists.txt @@ -0,0 +1,50 @@ +# SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.10) +project(com.example.aurora_push_example LANGUAGES CXX) + +include(GNUInstallDirs) + +set(BINARY_NAME ${CMAKE_PROJECT_NAME}) +set(FLUTTER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/flutter) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(CMAKE_CXX_FLAGS "-Wall -Wextra") +set(CMAKE_CXX_FLAGS_RELEASE "-O3") + +set(CMAKE_SKIP_RPATH OFF) +set(CMAKE_INSTALL_RPATH "\$ORIGIN/../share/${BINARY_NAME}/lib") + +find_package(PkgConfig REQUIRED) +pkg_check_modules(FlutterEmbedder REQUIRED IMPORTED_TARGET flutter-embedder) + +add_executable(${BINARY_NAME} main.cpp ${FLUTTER_DIR}/generated_plugin_registrant.cpp) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::FlutterEmbedder) +target_include_directories(${BINARY_NAME} PRIVATE ${FLUTTER_DIR}) + +include(flutter/generated_plugins.cmake) + +set(PACKAGE_INSTALL_DIR ${CMAKE_INSTALL_DATADIR}/${BINARY_NAME}) +set(DESKTOP_INSTALL_DIR ${CMAKE_INSTALL_DATADIR}/applications) +set(ICONS_INSTALL_ROOT_DIR ${CMAKE_INSTALL_DATADIR}/icons/hicolor) + +add_custom_command(TARGET ${BINARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/libflutter-embedder.so + ${PROJECT_BINARY_DIR}/bundle/lib/libflutter-embedder.so) + +install(FILES ${PROJECT_BINARY_DIR}/bundle/icudtl.dat DESTINATION ${PACKAGE_INSTALL_DIR}) +install(DIRECTORY ${PROJECT_BINARY_DIR}/bundle/flutter_assets DESTINATION ${PACKAGE_INSTALL_DIR}) +install(DIRECTORY ${PROJECT_BINARY_DIR}/bundle/lib DESTINATION ${PACKAGE_INSTALL_DIR}) + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +install(FILES desktop/${BINARY_NAME}.desktop DESTINATION ${DESKTOP_INSTALL_DIR}) + +foreach(ICONS_SIZE 86x86 108x108 128x128 172x172) + install(FILES icons/${ICONS_SIZE}.png + RENAME ${BINARY_NAME}.png + DESTINATION ${ICONS_INSTALL_ROOT_DIR}/${ICONS_SIZE}/apps/) +endforeach(ICONS_SIZE) diff --git a/packages/aurora_push_service/example/aurora/desktop/com.example.aurora_push_example.desktop b/packages/aurora_push_service/example/aurora/desktop/com.example.aurora_push_example.desktop new file mode 100644 index 0000000..09ab096 --- /dev/null +++ b/packages/aurora_push_service/example/aurora/desktop/com.example.aurora_push_example.desktop @@ -0,0 +1,15 @@ +[Desktop Entry] +Type=Application +Name=aurora_push_example +X-Nemo-Single-Instance=no +X-Aurora-Single-Cover=yes +X-Nemo-Application-Type=silica-qt5 +Comment=Demonstrates how to use the aurora_push plugin. +Icon=com.example.aurora_push_example +Exec=/usr/bin/com.example.aurora_push_example + +[X-Application] +Permissions=PushNotifications;Internet +OrganizationName=com.example +ApplicationName=aurora_push_example +ExecDBus=/usr/bin/com.example.aurora_push_example %u \ No newline at end of file diff --git a/packages/aurora_push_service/example/aurora/icons/108x108.png b/packages/aurora_push_service/example/aurora/icons/108x108.png new file mode 100644 index 0000000..984893d Binary files /dev/null and b/packages/aurora_push_service/example/aurora/icons/108x108.png differ diff --git a/packages/aurora_push_service/example/aurora/icons/128x128.png b/packages/aurora_push_service/example/aurora/icons/128x128.png new file mode 100644 index 0000000..2d552ef Binary files /dev/null and b/packages/aurora_push_service/example/aurora/icons/128x128.png differ diff --git a/packages/aurora_push_service/example/aurora/icons/172x172.png b/packages/aurora_push_service/example/aurora/icons/172x172.png new file mode 100644 index 0000000..9dc271b Binary files /dev/null and b/packages/aurora_push_service/example/aurora/icons/172x172.png differ diff --git a/packages/aurora_push_service/example/aurora/icons/86x86.png b/packages/aurora_push_service/example/aurora/icons/86x86.png new file mode 100644 index 0000000..5923bb1 Binary files /dev/null and b/packages/aurora_push_service/example/aurora/icons/86x86.png differ diff --git a/packages/aurora_push_service/example/aurora/main.cpp b/packages/aurora_push_service/example/aurora/main.cpp new file mode 100644 index 0000000..1e0f4ce --- /dev/null +++ b/packages/aurora_push_service/example/aurora/main.cpp @@ -0,0 +1,16 @@ +/** + * SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include "generated_plugin_registrant.h" + +int main(int argc, char *argv[]) +{ + Application::Initialize(argc, argv); + EnableQtCompatibility(); + RegisterPlugins(); + Application::Launch(); + return 0; +} diff --git a/packages/aurora_push_service/example/aurora/rpm/com.example.aurora_push_example.spec b/packages/aurora_push_service/example/aurora/rpm/com.example.aurora_push_example.spec new file mode 100644 index 0000000..507f21e --- /dev/null +++ b/packages/aurora_push_service/example/aurora/rpm/com.example.aurora_push_example.spec @@ -0,0 +1,39 @@ +%global __provides_exclude_from ^%{_datadir}/%{name}/lib/.*$ +%global __requires_exclude ^lib(dconf|flutter-embedder|maliit-glib|.+_platform_plugin)\\.so.*$ + +Name: com.example.aurora_push_example +Summary: Demonstrates how to use the aurora_push plugin. +Version: 0.2.0 +Release: 2 +License: Proprietary +Source0: %{name}-%{version}.tar.zst + +BuildRequires: cmake +BuildRequires: pkgconfig(flutter-embedder) +BuildRequires: pkgconfig(auroraapp) +BuildRequires: pkgconfig(Qt5Core) +BuildRequires: pkgconfig(Qt5Qml) +BuildRequires: pkgconfig(Qt5Quick) +BuildRequires: pkgconfig(Qt5DBus) +BuildRequires: pkgconfig(nemonotifications-qt5) +BuildRequires: pkgconfig(pushclient) >= 2.0.0 +Requires: sailfishsilica-qt5 >= 0.10.9 +Requires: nemo-qml-plugin-notifications-qt5 +%description +%{summary}. + +%prep +%autosetup + +%build +%cmake -DCMAKE_BUILD_TYPE=%{_flutter_build_type} +%make_build + +%install +%make_install + +%files +%{_bindir}/%{name} +%{_datadir}/%{name}/* +%{_datadir}/applications/%{name}.desktop +%{_datadir}/icons/hicolor/*/apps/%{name}.png diff --git a/packages/aurora_push_service/example/lib/main.dart b/packages/aurora_push_service/example/lib/main.dart new file mode 100644 index 0000000..5f1e21b --- /dev/null +++ b/packages/aurora_push_service/example/lib/main.dart @@ -0,0 +1,201 @@ +import 'package:flutter/material.dart'; +import 'dart:async'; + +import 'package:flutter/services.dart'; +import 'package:aurora_push_service/aurora_push_service.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatefulWidget { + const MyApp({super.key}); + + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { + final pushes = []; + final _auroraPushPlugin = const AuroraPushService(); + StreamSubscription? messagesSubscription; + String registrationId = ''; + int notificationCounterId = 0; + bool wasInitialized = false; + + Future initPlatformState(BuildContext context) async { + setState(() { + wasInitialized = false; + }); + try { + registrationId = await _auroraPushPlugin.initialize( + // TODO: добавьте ваш applicationId + applicationId: '', + ); + if (registrationId.isNotEmpty) setState(() {}); + messagesSubscription ??= + _auroraPushPlugin.onMessage.listen((event) async { + if (!mounted) return; + setState(() { + pushes.add(event); + }); + final notificationPlugin = FlutterLocalNotificationsPlugin(); + await notificationPlugin.show( + notificationCounterId++, + "#$notificationCounterId ${event.title}", + "${event.message}", + null, + ); + }); + } on Object catch (e) { + if (!mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(e.toString())), + ); + } + if (!mounted || registrationId.isEmpty) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Your registration id: $registrationId'), + action: SnackBarAction( + label: 'Copy', + onPressed: () async { + await Clipboard.setData(ClipboardData(text: registrationId)); + }, + ), + ), + ); + setState(() { + wasInitialized = true; + }); + } + + @override + void dispose() { + messagesSubscription?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + theme: ThemeData(useMaterial3: true), + home: Scaffold( + appBar: AppBar( + title: const Text('Plugin example app'), + ), + body: Column( + children: [ + if (!wasInitialized) + const Text( + 'Tap FAB to initialize AuroraPushService.', + ), + if (registrationId.isNotEmpty) + ListTile( + title: Text(registrationId), + trailing: IconButton( + icon: const Icon(Icons.copy), + onPressed: () async { + await Clipboard.setData( + ClipboardData(text: registrationId), + ); + }, + ), + ), + Expanded( + child: ListView.builder( + // Чтобы самые свежие пуши отображались в начале + itemCount: pushes.length, + itemBuilder: (context, index) { + final push = pushes.reversed.toList()[index]; + return ListTile( + title: Text('Title: ${push.title}'), + subtitle: Text('Message: ${push.message}'), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ListTileScreen( + title: push.title ?? '', + message: push.message ?? '', + data: push.data ?? '', + ), + ), + ); + }, + ); + }, + ), + ), + ], + ), + floatingActionButton: Builder( + builder: (context) { + return FloatingActionButton( + tooltip: 'Long tap to re-initialize', + onPressed: () async { + await initPlatformState(context); + }, + child: const Icon(Icons.replay), + ); + }, + ), + ), + ); + } +} + +class ListTileScreen extends StatelessWidget { + const ListTileScreen({ + super.key, + this.title = '', + this.message = '', + this.data = '', + }); + + final String title; + final String message; + final String data; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Push info'), + ), + body: Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (title.isNotEmpty) + ListTile( + title: Text('Title: $title'), + onTap: () async { + await Clipboard.setData( + ClipboardData(text: title), + ); + }, + ), + if (message.isNotEmpty) + ListTile( + title: Text('Message: $message'), + onTap: () async { + await Clipboard.setData( + ClipboardData(text: message), + ); + }, + ), + if (data.isNotEmpty) + ListTile( + title: Text('Data: $data'), + onTap: () async { + await Clipboard.setData( + ClipboardData(text: data), + ); + }, + ), + ], + ), + ); + } +} diff --git a/packages/aurora_push_service/example/pubspec.yaml b/packages/aurora_push_service/example/pubspec.yaml new file mode 100644 index 0000000..50411a1 --- /dev/null +++ b/packages/aurora_push_service/example/pubspec.yaml @@ -0,0 +1,28 @@ +name: aurora_push_example +description: Demonstrates how to use the aurora_push_service plugin. +version: 0.2.0+2 +publish_to: 'none' + +environment: + sdk: '>=2.18.6 <3.0.0' + +dependencies: + flutter: + sdk: flutter + aurora_push_service: + path: ../ + cupertino_icons: ^1.0.2 + flutter_local_notifications: ^14.1.1 + flutter_local_notifications_aurora: + git: + url: https://gitlab.com/omprussia/flutter/flutter-plugins.git + ref: b3679eec5067806020b01c388894ad536a278a98 + path: packages/flutter_local_notifications/flutter_local_notifications_aurora + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^2.0.2 + +flutter: + uses-material-design: true \ No newline at end of file diff --git a/packages/aurora_push_service/example/test/widget_test.dart b/packages/aurora_push_service/example/test/widget_test.dart new file mode 100644 index 0000000..913cfa6 --- /dev/null +++ b/packages/aurora_push_service/example/test/widget_test.dart @@ -0,0 +1,27 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility in the flutter_test package. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:aurora_push_example/main.dart'; + +void main() { + testWidgets('Verify Platform version', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + // Verify that platform version is retrieved. + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is Text && widget.data!.startsWith('Running on:'), + ), + findsOneWidget, + ); + }); +} diff --git a/packages/aurora_push_service/example/tools/build.md b/packages/aurora_push_service/example/tools/build.md new file mode 100644 index 0000000..f02dbee --- /dev/null +++ b/packages/aurora_push_service/example/tools/build.md @@ -0,0 +1,19 @@ +0) Подключаете телефон в режиме разработчика +1) Собираете под аврору +flutter build aurora --release + +2) Копируете полную ссылку на файл +если что она находится по пути /build/aurora/arm/release/RPMS/ +пример: +/home/mozerrr/src/projects/aurora_test_lab/packages/aurora_push/example/build/aurora/arm/release/RPMS/com.example.aurora_push_example-0.1.0-1.armv7hl.rpm + +3) Делаете подпись (сейчас только тестовый серт и ключ) +aurora_psdk rpmsign-external sign --key /home/mozerrr/src/aurora/cert/regular_key.pem --cert /home/mozerrr/src/aurora/cert/regular_cert.pem /home/mozerrr/src/projects/aurora_test_lab/packages/aurora_push/example/build/aurora/arm/release/RPMS/com.example.aurora_push_example-0.1.0-1.armv7hl.rpm + +4) Копируете на телефон +scp /home/mozerrr/src/projects/aurora_test_lab/packages/aurora_push/example/build/aurora/arm/release/RPMS/com.example.aurora_push_example-0.1.0-1.armv7hl.rpm defaultuser@192.168.2.15:/home/defaultuser/Downloads + +5) Устанавливаете +ssh defaultuser@192.168.2.15 +devel-su +pkcon install-local /home/defaultuser/Downloads/com.example.aurora_push_example-0.1.0-1.armv7hl.rpm -y \ No newline at end of file diff --git a/packages/aurora_push_service/lib/aurora_push_service.dart b/packages/aurora_push_service/lib/aurora_push_service.dart new file mode 100644 index 0000000..23dba51 --- /dev/null +++ b/packages/aurora_push_service/lib/aurora_push_service.dart @@ -0,0 +1,11 @@ +// Copyright (c) 2023, Friflex LLC. Please see the AUTHORS file +// for details. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library aurora_push_service; + +export 'src/aurora_push_message.dart'; +export 'src/aurora_push_platform_interface.dart'; +export 'src/aurora_push_service.dart'; +export 'src/method_channel_messaging.dart'; +export 'src/aurora_push_exception.dart'; diff --git a/packages/aurora_push_service/lib/src/aurora_push_exception.dart b/packages/aurora_push_service/lib/src/aurora_push_exception.dart new file mode 100644 index 0000000..40c7e1d --- /dev/null +++ b/packages/aurora_push_service/lib/src/aurora_push_exception.dart @@ -0,0 +1,50 @@ +// Copyright (c) 2023, Friflex LLC. Please see the AUTHORS file +// for details. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// ignore_for_file: prefer_const_constructors_in_immutables + +import 'package:flutter/foundation.dart'; + +@immutable +class AuroraPushException implements Exception { + AuroraPushException({ + this.message, + String? code, + this.stackTrace, + // ignore: unnecessary_this + }) : this.code = code ?? 'unknown'; + + /// The long form message of the exception. + final String? message; + + /// The optional code to accommodate the message. + /// + /// Allows users to identify the exception from a short code-name. + final String code; + + /// The stack trace which provides information to the user about the call + /// sequence that triggered an exception + final StackTrace? stackTrace; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + if (other is! AuroraPushException) return false; + return other.hashCode == hashCode; + } + + @override + int get hashCode => Object.hash(code, message); + + @override + String toString() { + String output = '[$code] $message'; + + if (stackTrace != null) { + output += '\n\n$stackTrace'; + } + + return output; + } +} diff --git a/packages/aurora_push_service/lib/src/aurora_push_message.dart b/packages/aurora_push_service/lib/src/aurora_push_message.dart new file mode 100644 index 0000000..1afb7b1 --- /dev/null +++ b/packages/aurora_push_service/lib/src/aurora_push_message.dart @@ -0,0 +1,67 @@ +// Copyright (c) 2023, Friflex LLC. Please see the AUTHORS file +// for details. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Модель с данными о пуш уведомлении. +/// +/// Подробнее: +/// * https://developer.auroraos.ru/doc/4.0.2/software_development/guides/push/client +class AuroraPushMessage { + /// Заголовок сообщения. + final String? title; + + /// Тело сообщения. + final String? message; + + /// Строка, содержащая сериализованный JSON-объект. + final String? data; + + /// Зарезервировано на будущее. + final String? action; + + /// Зарезервировано на будущее. + final String? sound; + + /// Зарезервировано на будущее. + final String? image; + + /// Зарезервировано на будущее. + final int? categoryId; + + /// Модель с данными о пуш уведомлении. + const AuroraPushMessage({ + this.title, + this.message, + this.data, + this.action, + this.sound, + this.image, + this.categoryId, + }); + + /// Returns the [AuroraPushMessage] from a raw [Map]. + factory AuroraPushMessage.fromMap(Map map) { + return AuroraPushMessage( + title: map['title'], + data: map['data'], + action: map['action'], + message: map['message'], + sound: map['sound'], + image: map['image'], + categoryId: map['categoryId'], + ); + } + + /// Returns the [AuroraPushMessage] as a raw [Map]. + Map toMap() { + return { + 'title': title, + 'data': data, + 'action': action, + 'message': message, + 'sound': sound, + 'image': image, + 'categoryId': categoryId, + }; + } +} diff --git a/packages/aurora_push_service/lib/src/aurora_push_platform_interface.dart b/packages/aurora_push_service/lib/src/aurora_push_platform_interface.dart new file mode 100644 index 0000000..ca40361 --- /dev/null +++ b/packages/aurora_push_service/lib/src/aurora_push_platform_interface.dart @@ -0,0 +1,44 @@ +// Copyright (c) 2023, Friflex LLC. Please see the AUTHORS file +// for details. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:aurora_push_service/src/aurora_push_message.dart'; +import 'package:aurora_push_service/src/method_channel_messaging.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +abstract class AuroraPushPlatform extends PlatformInterface { + /// Constructs a AuroraPushPlatform. + AuroraPushPlatform() : super(token: _token); + + static final Object _token = Object(); + + static AuroraPushPlatform? _instance; + + /// The default instance of [AuroraPushPlatform] to use. + /// + /// Defaults to [MethodChannelAuroraPush]. + static AuroraPushPlatform get instance { + if (_instance == null) { + MethodChannelAuroraMessaging.setMethodCallHandlers(); + instance = MethodChannelAuroraMessaging(); + } + return _instance!; + } + + /// Platform-specific implementations should set this with their own + /// platform-specific class that extends [AuroraPushPlatform] when + /// they register themselves. + static set instance(AuroraPushPlatform instance) { + PlatformInterface.verifyToken(instance, _token); + _instance = instance; + } + + Future initialize({required String applicationId}) { + throw UnimplementedError('init() has not been implemented.'); + } + + static final StreamController onMessage = + StreamController.broadcast(); +} diff --git a/packages/aurora_push_service/lib/src/aurora_push_service.dart b/packages/aurora_push_service/lib/src/aurora_push_service.dart new file mode 100644 index 0000000..437a049 --- /dev/null +++ b/packages/aurora_push_service/lib/src/aurora_push_service.dart @@ -0,0 +1,25 @@ +// Copyright (c) 2023, Friflex LLC. Please see the AUTHORS file +// for details. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:aurora_push_service/src/aurora_push_message.dart'; +import 'aurora_push_platform_interface.dart'; + +/// Сервис для получения пуш уведомлений от ОС Аврора и Аврора Центра. +class AuroraPushService { + const AuroraPushService(); + + /// Инициализация пуш сервиса. + /// + /// Можно вызывать несколько раз, но не имеет практического смысла. + Future initialize({required String applicationId}) { + return AuroraPushPlatform.instance.initialize(applicationId: applicationId); + } + + /// [Stream] с приходящими пушами от Аврора центра. + /// + /// По умолчанию они не показываются, поэтому нужно + /// использовать [FlutterLocalNotificationsPlugin](https://gitlab.com/omprussia/flutter/flutter-plugins/-/tree/master/packages/flutter_local_notifications/flutter_local_notifications_aurora?ref_type=heads). + Stream get onMessage => + AuroraPushPlatform.onMessage.stream; +} diff --git a/packages/aurora_push_service/lib/src/method_channel_messaging.dart b/packages/aurora_push_service/lib/src/method_channel_messaging.dart new file mode 100644 index 0000000..ff28d32 --- /dev/null +++ b/packages/aurora_push_service/lib/src/method_channel_messaging.dart @@ -0,0 +1,119 @@ +// Copyright (c) 2023, Friflex LLC. Please see the AUTHORS file +// for details. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:aurora_push_service/src/aurora_push_exception.dart'; +import 'package:aurora_push_service/src/aurora_push_message.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; + +import 'aurora_push_platform_interface.dart'; + +class MethodChannelAuroraMessaging extends AuroraPushPlatform { + @visibleForTesting + static const channel = MethodChannel('friflex/aurora_push'); + + @visibleForTesting + static Completer? initCompleter; + + static void setMethodCallHandlers() { + WidgetsFlutterBinding.ensureInitialized(); + MethodChannelAuroraMessaging.channel.setMethodCallHandler((call) async { + switch (call.method) { + case 'Messaging#onMessage': + final messageMap = Map.from(call.arguments); + AuroraPushPlatform.onMessage + .add(AuroraPushMessage.fromMap(messageMap)); + break; + case 'Messaging#onReadinessChanged': + final isAvailable = call.arguments as bool; + if (!isAvailable) { + initCompleter?.completeError(AuroraPushException( + code: 'push_system_not_available', + message: 'todo: Push system is not available', + )); + } + break; + case 'Messaging#onRegistrationError': + // На данный момент от платформы не приходит информация о причине + // ошибки при регистрации. Также не понятно когда оно приходит. + final message = call.arguments.toString(); + initCompleter?.completeError(AuroraPushException( + code: 'registration_error', + message: message, + )); + break; + case 'Messaging#applicationRegistered': + final registrationId = call.arguments as String; + initCompleter?.complete(registrationId); + break; + } + }); + } + + @override + Future initialize({required String applicationId}) async { + if (initCompleter != null) { + throw AuroraPushException( + code: 'init_completer_not_finished', + message: + 'initCompleter not finished. You must not call initialize before finishing.', + ); + } + if (applicationId.isEmpty) { + throw AuroraPushException( + code: 'application_id_empty', + message: + 'ApplicationId is empty. Set applicationId from Aurora Center.', + ); + } + await channel.invokeMethod('Messaging#init', { + 'applicationId': applicationId, + }); + initCompleter = Completer(); + // Ждем исполнения Messaging#onReadinessChanged и Messaging#applicationRegistered + // Также может вернуться ошибка в Messaging#onRegistrationError + try { + // При возникновении нетипичных ошибок Aurora не возвращает ошибки, + // поэтому нужно ставить timeout. + final registrationId = await initCompleter!.future.timeout( + const Duration(seconds: 5), + ); + // Сбрасываем initCompleter чтобы не вызывать потенциальных ошибок с + // получением нескольких колбеков от аврора-side плагина. + initCompleter = null; + return registrationId; + } on TimeoutException catch (e, s) { + initCompleter = null; + + /// Эта ошибка может происходить по разным причинам. + /// + /// К сожалению, сейчас api не предоставляет ошибок по каким именно + /// причинам не удалось получить [registrationId]. + /// + /// Для получения логов запуска пуш сервиса запустите приложение + /// через консоль. + /// + /// Troubleshoot: + /// * Проверьте подключение телефона к Аврора Центру. + /// * Проверьте валидность [applicationId]. Если в консоли вы + /// видите "Can not request push notifications right now", значит + /// проблема с невалидным applicationId. + /// * Проверьте интернет соединение пользователя. + /// * Проверьте соединение с Аврора Центром. + Error.throwWithStackTrace( + AuroraPushException( + code: 'response_timeout', + message: + 'initialize(applicationId: $applicationId) вернул TimeoutException', + ), + s, + ); + } on Object { + initCompleter = null; + rethrow; + } + } +} diff --git a/packages/aurora_push_service/mono_pkg.yaml b/packages/aurora_push_service/mono_pkg.yaml new file mode 100644 index 0000000..cfaf470 --- /dev/null +++ b/packages/aurora_push_service/mono_pkg.yaml @@ -0,0 +1,26 @@ +# Every entry must be associated with at least one SDK version – corresponding +# to the Dart SDK version or the Flutter framework version, depending on the +# type of package. It can be specified at the top-lever as a single value or +# an array. Alternatively, you can specify the SDK version(s) within each job. +sdk: + # Specific `pubspec` to test the lower-bound SDK defined in pubspec.yaml + # This is only supported for Dart packages (not Flutter). + - stable + - "3.3.10" + +stages: + # Register two jobs to run under the `analyze` stage. + - analyze: + - analyze + - format + - unit_test: + - test + # Example cron stage which will only run for scheduled jobs (here we run + # multiple OS configs for extra validation as an example). + # + # See the `mono_repo.yaml` example above for where this stage is specially + # configured. + - cron: + - test: + os: + - linux \ No newline at end of file diff --git a/packages/aurora_push_service/pubspec.yaml b/packages/aurora_push_service/pubspec.yaml new file mode 100644 index 0000000..bea4887 --- /dev/null +++ b/packages/aurora_push_service/pubspec.yaml @@ -0,0 +1,26 @@ +name: aurora_push_service +description: A new Flutter plugin project. +version: 0.2.0 +publish_to: https://pub-aurora.friflex.com +homepage: "https://github.com/smmarty/aurora_flutter/tree/main/packages/aurora_push_service" + +environment: + sdk: '>=2.18.6 <4.0.0' + flutter: ">=3.3.10" + +dependencies: + flutter: + sdk: flutter + plugin_platform_interface: ^2.0.2 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^2.0.0 + fake_async: ^1.3.1 + +flutter: + plugin: + platforms: + aurora: + pluginClass: AuroraPushPlugin \ No newline at end of file diff --git a/packages/aurora_push_service/test/aurora_push_method_channel_test.dart b/packages/aurora_push_service/test/aurora_push_method_channel_test.dart new file mode 100644 index 0000000..38561a7 --- /dev/null +++ b/packages/aurora_push_service/test/aurora_push_method_channel_test.dart @@ -0,0 +1,74 @@ +// Copyright (c) 2023, Friflex LLC. Please see the AUTHORS file +// for details. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:aurora_push_service/aurora_push_service.dart'; +import 'package:fake_async/fake_async.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + late AuroraPushService pushService; + + setUp(() { + TestWidgetsFlutterBinding.ensureInitialized(); + pushService = const AuroraPushService(); + }); + + test('initialize throws application_id_empty exception', () async { + expect( + () => pushService.initialize(applicationId: ''), + throwsA(AuroraPushException( + code: 'application_id_empty', + message: + 'ApplicationId is empty. Set applicationId from Aurora Center.', + ))); + }); + + testWidgets('initialize throws TimeoutException after 5 seconds', + (tester) async { + fakeAsync((async) { + tester.binding.defaultBinaryMessenger.setMockMethodCallHandler( + MethodChannelAuroraMessaging.channel, (message) async { + if (message.method == 'Messaging#init') { + return null; + } + return null; + }); + const appId = 'asd'; + expect( + () => pushService.initialize(applicationId: appId), + throwsA(AuroraPushException( + code: 'response_timeout', + message: + 'initialize(applicationId: $appId) вернул TimeoutException', + ))); + async.elapse(const Duration(seconds: 6)); + }); + }); + + testWidgets( + 'initialize throws init_completer_not_finished if called when calling initialize', + (tester) async { + fakeAsync((async) { + tester.binding.defaultBinaryMessenger.setMockMethodCallHandler( + MethodChannelAuroraMessaging.channel, (message) async { + if (message.method == 'Messaging#init') { + return null; + } + return null; + }); + const appId = 'asd'; + pushService.initialize(applicationId: appId); + async.elapse(const Duration(seconds: 3)); + expect( + () => pushService.initialize(applicationId: appId), + throwsA(AuroraPushException( + code: 'init_completer_not_finished', + message: + '_initCompleter not finished. You must not call initialize before finishing.', + ))); + // fix infinity test + async.flushMicrotasks(); + }); + }); +} diff --git a/tool/ci.sh b/tool/ci.sh new file mode 100755 index 0000000..422357c --- /dev/null +++ b/tool/ci.sh @@ -0,0 +1,115 @@ +#!/bin/bash +# Created with package:mono_repo v6.6.0 + +# Support built in commands on windows out of the box. +# When it is a flutter repo (check the pubspec.yaml for "sdk: flutter") +# then "flutter" is called instead of "pub". +# This assumes that the Flutter SDK has been installed in a previous step. +function pub() { + if grep -Fq "sdk: flutter" "${PWD}/pubspec.yaml"; then + command flutter pub "$@" + else + command dart pub "$@" + fi +} +# When it is a flutter repo (check the pubspec.yaml for "sdk: flutter") +# then "flutter" is called instead of "pub". +# This assumes that the Flutter SDK has been installed in a previous step. +function format() { + if grep -Fq "sdk: flutter" "${PWD}/pubspec.yaml"; then + command flutter format "$@" + else + command dart format "$@" + fi +} +# When it is a flutter repo (check the pubspec.yaml for "sdk: flutter") +# then "flutter" is called instead of "pub". +# This assumes that the Flutter SDK has been installed in a previous step. +function analyze() { + if grep -Fq "sdk: flutter" "${PWD}/pubspec.yaml"; then + command flutter analyze "$@" + else + command dart analyze "$@" + fi +} + +if [[ -z ${PKGS} ]]; then + echo -e '\033[31mPKGS environment variable must be set! - TERMINATING JOB\033[0m' + exit 64 +fi + +if [[ "$#" == "0" ]]; then + echo -e '\033[31mAt least one task argument must be provided! - TERMINATING JOB\033[0m' + exit 64 +fi + +SUCCESS_COUNT=0 +declare -a FAILURES + +for PKG in ${PKGS}; do + echo -e "\033[1mPKG: ${PKG}\033[22m" + EXIT_CODE=0 + pushd "${PKG}" >/dev/null || EXIT_CODE=$? + + if [[ ${EXIT_CODE} -ne 0 ]]; then + echo -e "\033[31mPKG: '${PKG}' does not exist - TERMINATING JOB\033[0m" + exit 64 + fi + + dart pub upgrade || EXIT_CODE=$? + + if [[ ${EXIT_CODE} -ne 0 ]]; then + echo -e "\033[31mPKG: ${PKG}; 'dart pub upgrade' - FAILED (${EXIT_CODE})\033[0m" + FAILURES+=("${PKG}; 'dart pub upgrade'") + else + for TASK in "$@"; do + EXIT_CODE=0 + echo + echo -e "\033[1mPKG: ${PKG}; TASK: ${TASK}\033[22m" + case ${TASK} in + analyze) + echo 'flutter analyze' + flutter analyze || EXIT_CODE=$? + ;; + format) + echo 'dart format --output=none --set-exit-if-changed .' + dart format --output=none --set-exit-if-changed . || EXIT_CODE=$? + ;; + test) + echo 'flutter test' + flutter test || EXIT_CODE=$? + ;; + *) + echo -e "\033[31mUnknown TASK '${TASK}' - TERMINATING JOB\033[0m" + exit 64 + ;; + esac + + if [[ ${EXIT_CODE} -ne 0 ]]; then + echo -e "\033[31mPKG: ${PKG}; TASK: ${TASK} - FAILED (${EXIT_CODE})\033[0m" + FAILURES+=("${PKG}; TASK: ${TASK}") + else + echo -e "\033[32mPKG: ${PKG}; TASK: ${TASK} - SUCCEEDED\033[0m" + SUCCESS_COUNT=$((SUCCESS_COUNT + 1)) + fi + + done + fi + + echo + echo -e "\033[32mSUCCESS COUNT: ${SUCCESS_COUNT}\033[0m" + + if [ ${#FAILURES[@]} -ne 0 ]; then + echo -e "\033[31mFAILURES: ${#FAILURES[@]}\033[0m" + for i in "${FAILURES[@]}"; do + echo -e "\033[31m $i\033[0m" + done + fi + + popd >/dev/null || exit 70 + echo +done + +if [ ${#FAILURES[@]} -ne 0 ]; then + exit 1 +fi