Shared preferences See merge request non-oss/flutter/flutter-plugins!2merge-requests/2/merge
@ -0,0 +1,7 @@
|
||||
# Authors |
||||
|
||||
* Denis Glazkov, <d.glazkov@omp.ru> |
||||
* Product owner, 2023 |
||||
* Maintainer, 2023 |
||||
|
||||
* Vitaliy Zarubin, <v.zarubin@omp.ru> |
@ -0,0 +1,83 @@
|
||||
# Code of Conduct |
||||
|
||||
## What is this code of conduct for? |
||||
|
||||
Code of conduct is a current set of rules of the Open Mobile Platform |
||||
which informs you how we expect |
||||
the members of the Open Mobile Platform community |
||||
will interact while contributing and communicating. |
||||
We are committed to providing a friendly, safe and welcoming |
||||
environment for all, regardless of gender, gender identity and expression, |
||||
sexual orientation, ability, physical appearance, body size, race, age, |
||||
socioeconomic status, religion (or lack thereof), |
||||
or other marginalized aspect of community members. |
||||
We expect all members of the Open Mobile Platform community |
||||
to abide by this Code of Conduct whenever interacting |
||||
in Open Mobile Platform venues |
||||
(merge requests, pull requests, issues, 1-1 or group chat, meetups, conferences, etc.) |
||||
|
||||
## Examples of appropriate behavior |
||||
|
||||
* Using welcoming and inclusive language. |
||||
* Being respectful of differing viewpoints and experiences. |
||||
* Gracefully accepting constructive criticism. |
||||
* Focusing on what is best for the community. |
||||
* Showing empathy towards other community members. |
||||
|
||||
## Examples of inappropriate behavior |
||||
|
||||
Because we come from a variety of backgrounds, |
||||
we do not want to assume that everyone has the same assumptions |
||||
about what is and is not appropriate. |
||||
Here are some examples of inappropriate behavior |
||||
that are incompatible with our community's ethos: |
||||
|
||||
* spamming, trolling, intentionally disrupting conversations, |
||||
or irrelevant solicitation or advertisement; |
||||
* making demeaning or discriminatory comments; |
||||
* making negative assumptions about someone's background, |
||||
abilities, or intentions; |
||||
* harassing or stalking individuals (online or in person). |
||||
|
||||
In general: treat others how you would like to be treated, |
||||
were you in their place. |
||||
Do ask questions. |
||||
Do keep conflicts productively focused on technical issues. |
||||
Do remember that we are all people, not robots, |
||||
and all equally deserving of sensitivity and respect. |
||||
|
||||
## What will organizers do about inappropriate behavior? |
||||
|
||||
If we notice you doing or saying something inappropriate, |
||||
an organizer will ask you to stop. |
||||
We will not demonize you. |
||||
But please do stop the inappropriate behavior |
||||
so we can get back to writing and discussing code in a safe environment. |
||||
If you have philosophical disagreements about what is actually inappropriate, |
||||
please take them to a separate public or private conversation |
||||
with an Open Mobile Platform maintainer |
||||
so we don't turn pull requests into an ethics debate. |
||||
If you keep doing unacceptable things, |
||||
we will likely ban you, report you to the administration, |
||||
or take other appropriate action. |
||||
|
||||
## What if I see or am subject to what feels like inappropriate behavior? |
||||
|
||||
Let us know. |
||||
Please notify a community organizer as soon as possible. |
||||
Full contact information is listed in the Contact Info section of this document. |
||||
All communications will be kept strictly confidential, |
||||
unless otherwise required by law. |
||||
No issue will be considered too inconsequential or unimportant for us |
||||
to have a conversation about. |
||||
|
||||
## Contact Info |
||||
|
||||
If you need to report an incident, |
||||
please contact <community@omp.ru>. |
||||
|
||||
This work is licensed under a Creative Commons Attribution 3.0 Unported License |
||||
For attribution requirements: |
||||
«Open Mobile Platform Code of Conduct» |
||||
Copyright (c) 2021 Open Mobile Platform LLC, |
||||
used under a [Creative Commons Attribution Unported license](http://creativecommons.org/licenses/by/3.0/). |
@ -0,0 +1,169 @@
|
||||
# Contributor License Agreements |
||||
|
||||
Thank you for your interest in contributing |
||||
to software projects managed by Open Mobile Platform («We» or «Us»). |
||||
This contributor agreement («Agreement») |
||||
documents the rights granted by contributors to Us. |
||||
To make this document effective, |
||||
please sign it and send it to Us by email or electronic submission. |
||||
This is a legally binding document, |
||||
so please read it carefully before agreeing to it. |
||||
The Agreement may cover more than one software project managed by Us. |
||||
|
||||
## 1. Definitions |
||||
|
||||
**«We» or «Us»** means Open Mobile Platform Limited Liability Company |
||||
(Open Mobile Platform LLC), |
||||
420500, Republic of Tatarstan, Verkhneuslonsky District, |
||||
Innopolis, Universitetskaya Street, h. 7, office 59, |
||||
OGRN (Primary State Registration Number) 1161690087020. |
||||
|
||||
**«You»** means the individual who Submits a Contribution to Us. |
||||
|
||||
**«Contribution»** means any work of authorship |
||||
that is Submitted by You to Us |
||||
in which You own or assert ownership of the Copyright. |
||||
|
||||
**«Copyright»** means all rights protecting works of authorship |
||||
owned or controlled by You, |
||||
including copyright, moral and neighboring rights, as appropriate, |
||||
for the full term of their existence including any extensions by You. |
||||
|
||||
**«Material»** means the work of authorship |
||||
which is made available by Us to third parties. |
||||
When this Agreement covers more than one software project, |
||||
the Material means the work of authorship |
||||
to which the Contribution was Submitted. |
||||
After You Submit the Contribution, |
||||
it may be included in the Material. |
||||
|
||||
**«Submit»** means any form of electronic, verbal, or written communication |
||||
sent to Us or our representatives, |
||||
including but not limited to electronic mailing lists, |
||||
source code control systems, and issue tracking systems |
||||
that are managed by, or on behalf of, Us |
||||
for the purpose of discussing and improving the Material, |
||||
but excluding communication that is conspicuously marked |
||||
or otherwise designated in writing by You as «Not a Contribution». |
||||
|
||||
**«Submission Date»** means the date |
||||
on which You Submit a Contribution to Us. |
||||
|
||||
**«Effective Date»** means the date You execute this Agreement |
||||
or the date You first Submit a Contribution to Us, |
||||
whichever is earlier. |
||||
|
||||
**«Media»** means any portion of a Contribution which is not software. |
||||
|
||||
## 2. Grant of Rights |
||||
|
||||
### 2.1. Copyright License |
||||
|
||||
(a) You retain ownership of the Copyright in Your Contribution |
||||
and have the same rights to use or license the Contribution |
||||
which You would have had without entering into the Agreement. |
||||
|
||||
(b) To the maximum extent permitted by the relevant law, |
||||
You grant to Us a perpetual, worldwide, non-exclusive, |
||||
transferable, royalty-free, irrevocable license |
||||
under the Copyright covering the Contribution, |
||||
with the right to sublicense |
||||
such rights through multiple tiers of sublicensees, |
||||
to reproduce, modify, display, perform and distribute |
||||
the Contribution as part of the Material; |
||||
provided that this license is conditioned upon compliance with Section 2.3. |
||||
|
||||
### 2.2. Patent License |
||||
|
||||
For patent claims including, without limitation, |
||||
method, process, and apparatus claims |
||||
which You own, control or have the right to grant, now or in the future, |
||||
You grant to Us a perpetual, worldwide, non-exclusive, |
||||
transferable, royalty-free, irrevocable patent license, |
||||
with the right to sublicense these rights to multiple tiers of sublicensees, |
||||
to make, have made, use, sell, offer for sale, import |
||||
and otherwise transfer the Contribution |
||||
and the Contribution in combination with the Material |
||||
(and portions of such combination). |
||||
This license is granted only to the extent |
||||
that the exercise of the licensed rights infringes such patent claims; |
||||
and provided that this license is conditioned upon compliance with Section 2.3. |
||||
|
||||
### 2.3. Outbound License |
||||
|
||||
Based on the grant of rights in Sections 2.1 and 2.2, |
||||
if We include Your Contribution in a Material, |
||||
We may license the Contribution under any license, |
||||
including copyleft, permissive, commercial, or proprietary licenses. |
||||
As a condition on the exercise of this right, |
||||
We agree to also license the Contribution |
||||
under the terms of the license or licenses |
||||
which We are using for the Material on the Submission Date. |
||||
|
||||
### 2.4. Our Rights |
||||
|
||||
You acknowledge that We are not obligated |
||||
to use Your Contribution as part of the Material |
||||
and may decide to include any Contribution We consider appropriate. |
||||
|
||||
## 3. Agreement |
||||
|
||||
You confirm that: |
||||
|
||||
(a) You have the legal authority to enter into this Agreement. |
||||
|
||||
(b) You own the Copyright and patent claims |
||||
covering the Contribution which are required |
||||
to grant the rights under Section 2. |
||||
|
||||
(c) The grant of rights under Section 2 |
||||
does not violate any grant of rights |
||||
which You have made to third parties, including Your employer. |
||||
If You are an employee, |
||||
You have had Your employer approve this Agreement |
||||
or sign the Entity version of this document. |
||||
If You are less than eighteen years old, |
||||
please have Your parents or guardian sign the Agreement. |
||||
|
||||
## 4. Disclaimer |
||||
|
||||
EXCEPT FOR THE EXPRESS WARRANTIES IN SECTION 3, |
||||
THE CONTRIBUTION IS PROVIDED «AS IS». |
||||
MORE PARTICULARLY, ALL EXPRESS OR IMPLIED WARRANTIES |
||||
INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTY OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE |
||||
AND NON-INFRINGEMENT ARE EXPRESSLY DISCLAIMED BY YOU TO US. |
||||
TO THE EXTENT THAT ANY SUCH WARRANTIES CANNOT BE DISCLAIMED, |
||||
SUCH WARRANTY IS LIMITED IN DURATION TO THE MINIMUM PERIOD PERMITTED BY LAW. |
||||
|
||||
## 5. Miscellaneous |
||||
|
||||
5.1. This Agreement will be governed by and construed |
||||
in accordance with the laws of Russian Federation. |
||||
|
||||
5.2. This Agreement sets out the entire agreement between You |
||||
and Us for Your Contributions to Us |
||||
and overrides all other agreements or understandings. |
||||
|
||||
5.3. If You or We assign the rights or obligations |
||||
received through this Agreement to a third party, |
||||
as a condition of the assignment, |
||||
that third party must agree in writing |
||||
to abide by all the rights and obligations in the Agreement. |
||||
|
||||
5.4. The failure of either party to require performance |
||||
by the other party of any provision of this Agreement in one situation |
||||
shall not affect the right of a party |
||||
to require such performance at any time in the future. |
||||
A waiver of performance under a provision in one situation |
||||
shall not be considered a waiver of the performance |
||||
of the provision in the future or a waiver of the provision in its entirety. |
||||
|
||||
5.5. If any provision of this Agreement is found void and unenforceable, |
||||
such provision will be replaced to the extent possible with a provision |
||||
that comes closest to the meaning of the original provision |
||||
and which is enforceable. |
||||
The terms and conditions set forth in this Agreement |
||||
shall apply notwithstanding any failure of essential purpose |
||||
of this Agreement or any limited remedy |
||||
to the maximum extent possible under law. |
@ -0,0 +1,30 @@
|
||||
# The 3-Clause BSD License |
||||
|
||||
_Copyright (C) 2022 ru.auroraos_ |
||||
|
||||
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. |
@ -0,0 +1,5 @@
|
||||
# Flutter Packages Aurora OS |
||||
|
||||
This repo is a companion repo to the main flutter repo. |
||||
It contains the source code for Aurora Flutter's packages (i.e., packages developed by the Aurora team). |
||||
Check the packages directory to see all packages. |
@ -0,0 +1,31 @@
|
||||
# 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/ |
||||
/.metadata |
@ -0,0 +1,41 @@
|
||||
# path_provider_aurora |
||||
|
||||
The Aurora OS implementation of [`path_provider`](https://pub.dev/packages/path_provider). |
||||
Documentation for setting permissions can be found [here](https://developer.auroraos.ru/doc/software_development/reference/user_data). |
||||
|
||||
## Usage |
||||
|
||||
This package is not an _endorsed_ implementation of `path_provider`. |
||||
Therefore, you have to include `path_provider_aurora` alongside `path_provider` as dependencies in your `pubspec.yaml` file. |
||||
|
||||
```yaml |
||||
dependencies: |
||||
path_provider: ^2.0.14 |
||||
path_provider_aurora: ^0.0.0 # @todo Not published |
||||
``` |
||||
|
||||
Then you can import `path_provider` in your Dart code: |
||||
|
||||
```dart |
||||
import 'package:path_provider/path_provider.dart'; |
||||
``` |
||||
|
||||
## Supported APIs |
||||
|
||||
- [x] `getTemporaryDirectory` |
||||
- [ ] `getApplicationSupportDirectory` |
||||
- [ ] `getLibraryDirectory` |
||||
- [x] `getApplicationDocumentsDirectory` |
||||
- [ ] `getExternalStorageDirectory` |
||||
- [ ] `getExternalCacheDirectories` |
||||
- [x] `getExternalStorageDirectories` (There is no concept of External in Aurora OS, but this interface allows you to get the pictures/music/movies directory) |
||||
- [x] `getDownloadsDirectory` |
||||
|
||||
## Extra methods |
||||
|
||||
PathProviderAurora.getApplicationOrg(); |
||||
PathProviderAurora.getApplicationName(); |
||||
|
||||
### Preview example |
||||
|
||||
 |
@ -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 |
@ -0,0 +1,23 @@
|
||||
cmake_minimum_required(VERSION 3.10) |
||||
|
||||
set(PROJECT_NAME path_provider_aurora) |
||||
set(PLUGIN_NAME path_provider_aurora_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") |
||||
|
||||
find_package(PkgConfig REQUIRED) |
||||
pkg_check_modules(FlutterEmbedder REQUIRED IMPORTED_TARGET flutter-embedder) |
||||
|
||||
add_library(${PLUGIN_NAME} SHARED path_provider_aurora_plugin.cpp) |
||||
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) |
||||
target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::FlutterEmbedder) |
||||
|
||||
target_include_directories(${PLUGIN_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) |
||||
target_compile_definitions(${PLUGIN_NAME} PRIVATE PLUGIN_IMPL) |
@ -0,0 +1,24 @@
|
||||
#ifndef FLUTTER_PLUGIN_PATH_PROVIDER_AURORA_PLUGIN_H |
||||
#define FLUTTER_PLUGIN_PATH_PROVIDER_AURORA_PLUGIN_H |
||||
|
||||
#include <flutter/plugin-interface.h> |
||||
|
||||
#ifdef PLUGIN_IMPL |
||||
#define PLUGIN_EXPORT __attribute__((visibility("default"))) |
||||
#else |
||||
#define PLUGIN_EXPORT |
||||
#endif |
||||
|
||||
class PLUGIN_EXPORT PathProviderAuroraPlugin final : public PluginInterface |
||||
{ |
||||
public: |
||||
void RegisterWithRegistrar(PluginRegistrar ®istrar) override; |
||||
|
||||
private: |
||||
void onMethodCall(const MethodCall &call); |
||||
void onGetApplicationOrg(const MethodCall &call); |
||||
void onGetApplicationName(const MethodCall &call); |
||||
void unimplemented(const MethodCall &call); |
||||
}; |
||||
|
||||
#endif /* FLUTTER_PLUGIN_PATH_PROVIDER_AURORA_PLUGIN_H */ |
@ -0,0 +1,42 @@
|
||||
#include <path_provider_aurora/path_provider_aurora_plugin.h> |
||||
#include <flutter/method-channel.h> |
||||
#include <flutter/application.h> |
||||
#include <sys/utsname.h> |
||||
|
||||
void PathProviderAuroraPlugin::RegisterWithRegistrar(PluginRegistrar ®istrar) |
||||
{ |
||||
registrar.RegisterMethodChannel("path_provider_aurora", |
||||
MethodCodecType::Standard, |
||||
[this](const MethodCall &call) { this->onMethodCall(call); }); |
||||
} |
||||
|
||||
void PathProviderAuroraPlugin::onMethodCall(const MethodCall &call) |
||||
{ |
||||
const auto &method = call.GetMethod(); |
||||
|
||||
if (method == "getApplicationOrg") { |
||||
onGetApplicationOrg(call); |
||||
return; |
||||
} |
||||
else if (method == "getApplicationName") { |
||||
onGetApplicationName(call); |
||||
return; |
||||
} |
||||
|
||||
unimplemented(call); |
||||
} |
||||
|
||||
void PathProviderAuroraPlugin::onGetApplicationOrg(const MethodCall &call) |
||||
{ |
||||
call.SendSuccessResponse(Application::GetID().orgname); |
||||
} |
||||
|
||||
void PathProviderAuroraPlugin::onGetApplicationName(const MethodCall &call) |
||||
{ |
||||
call.SendSuccessResponse(Application::GetID().appname); |
||||
} |
||||
|
||||
void PathProviderAuroraPlugin::unimplemented(const MethodCall &call) |
||||
{ |
||||
call.SendSuccessResponse(nullptr); |
||||
} |
After Width: | Height: | Size: 157 KiB |
@ -0,0 +1,44 @@
|
||||
# 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/ |
||||
|
||||
# Symbolication related |
||||
app.*.symbols |
||||
|
||||
# Obfuscation related |
||||
app.*.map.json |
||||
|
||||
# Android Studio will place build artifacts here |
||||
/android/app/debug |
||||
/android/app/profile |
||||
/android/app/release |
@ -0,0 +1,16 @@
|
||||
# path_provider_aurora_example |
||||
|
||||
Demonstrates how to use the path_provider_aurora 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. |
@ -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 |
@ -0,0 +1 @@
|
||||
flutter/ephemeral |
@ -0,0 +1,47 @@
|
||||
cmake_minimum_required(VERSION 3.10) |
||||
project(com.example.path_provider_aurora_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) |
@ -0,0 +1,12 @@
|
||||
[Desktop Entry] |
||||
Type=Application |
||||
Name=path_provider_aurora_example |
||||
Comment=Demonstrates how to use the path_provider_aurora plugin. |
||||
Icon=com.example.path_provider_aurora_example |
||||
Exec=/usr/bin/com.example.path_provider_aurora_example |
||||
X-Nemo-Application-Type=silica-qt5 |
||||
|
||||
[X-Application] |
||||
Permissions=UserDirs |
||||
OrganizationName=com.example |
||||
ApplicationName=path_provider_aurora_example |
@ -0,0 +1,16 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include <flutter/application.h> |
||||
#include <path_provider_aurora/path_provider_aurora_plugin.h> |
||||
|
||||
#include "generated_plugin_registrant.h" |
||||
|
||||
void RegisterPlugins() { |
||||
Application::RegisterPlugins({ |
||||
std::make_shared<PathProviderAuroraPlugin>(), |
||||
}); |
||||
} |
@ -0,0 +1,12 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifndef GENERATED_PLUGIN_REGISTRANT |
||||
#define GENERATED_PLUGIN_REGISTRANT |
||||
|
||||
void RegisterPlugins(); |
||||
|
||||
#endif /* GENERATED_PLUGIN_REGISTRANT */ |
@ -0,0 +1,32 @@
|
||||
# |
||||
# Generated file, do not edit. |
||||
# |
||||
set(ROOT_PROJECT_BINARY_DIR "${PROJECT_BINARY_DIR}") |
||||
|
||||
function(add_library TARGET) |
||||
_add_library(${TARGET} ${ARGN}) |
||||
|
||||
if(NOT "${TARGET}" MATCHES "^PkgConfig::.*") |
||||
add_custom_command(TARGET ${TARGET} POST_BUILD |
||||
COMMAND ${CMAKE_COMMAND} -E copy |
||||
"$<TARGET_FILE:${TARGET}>" |
||||
"${ROOT_PROJECT_BINARY_DIR}/bundle/lib/$<TARGET_FILE_NAME:${TARGET}>") |
||||
endif(NOT "${TARGET}" MATCHES "^PkgConfig::.*") |
||||
endfunction() |
||||
|
||||
list(APPEND FLUTTER_PLATFORM_PLUGIN_LIST |
||||
path_provider_aurora |
||||
) |
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST |
||||
xdga_directories |
||||
) |
||||
|
||||
foreach(PLUGIN ${FLUTTER_PLATFORM_PLUGIN_LIST}) |
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${PLUGIN}/aurora plugins/${PLUGIN}) |
||||
target_link_libraries(${BINARY_NAME} PRIVATE ${PLUGIN}_platform_plugin) |
||||
endforeach(PLUGIN) |
||||
|
||||
foreach(FFI_PLUGIN ${FLUTTER_FFI_PLUGIN_LIST}) |
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${FFI_PLUGIN}/aurora plugins/${FFI_PLUGIN}) |
||||
endforeach(FFI_PLUGIN) |
After Width: | Height: | Size: 9.7 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 6.5 KiB |
@ -0,0 +1,10 @@
|
||||
#include <flutter/application.h> |
||||
#include "generated_plugin_registrant.h" |
||||
|
||||
int main(int argc, char *argv[]) { |
||||
Application::Initialize(argc, argv); |
||||
Application::SetPixelRatio(1.8); |
||||
RegisterPlugins(); |
||||
Application::Launch(); |
||||
return 0; |
||||
} |
@ -0,0 +1,31 @@
|
||||
%global __provides_exclude_from ^%{_datadir}/%{name}/lib/.*$ |
||||
%global __requires_exclude ^lib(dconf|flutter-embedder|maliit-glib|appmanifest-.+|.+_platform_plugin)\\.so.*$ |
||||
|
||||
Name: com.example.path_provider_aurora_example |
||||
Summary: Demonstrates how to use the path_provider_aurora plugin. |
||||
Version: 0.1.0 |
||||
Release: 1 |
||||
License: Proprietary |
||||
Source0: %{name}-%{version}.tar.zst |
||||
|
||||
BuildRequires: cmake |
||||
BuildRequires: pkgconfig(flutter-embedder) |
||||
|
||||
%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 |
@ -0,0 +1,249 @@
|
||||
import 'dart:io'; |
||||
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:path_provider/path_provider.dart'; |
||||
import 'package:path_provider_aurora/path_provider_aurora.dart'; |
||||
|
||||
void main() { |
||||
runApp(const MyApp()); |
||||
} |
||||
|
||||
class MyApp extends StatefulWidget { |
||||
const MyApp({super.key}); |
||||
|
||||
@override |
||||
State<MyApp> createState() => _MyAppState(); |
||||
} |
||||
|
||||
class _MyAppState extends State<MyApp> { |
||||
String? _error; |
||||
String? _applicationOrg; |
||||
String? _applicationName; |
||||
String? _pathApplicationSupportDirectory; |
||||
String? _pathTempDirectory; |
||||
String? _pathApplicationDocumentsPath; |
||||
String? _pathDownloadsPath; |
||||
String? _pathPictures; |
||||
String? _pathMusic; |
||||
String? _pathMovies; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
loadPathDirectory(); |
||||
} |
||||
|
||||
/// Asynchronous function receiving directory paths |
||||
Future<void> loadPathDirectory() async { |
||||
try { |
||||
// Get names |
||||
String? applicationOrg = await PathProviderAurora.getApplicationOrg(); |
||||
String? applicationName = await PathProviderAurora.getApplicationName(); |
||||
|
||||
// Get directories |
||||
Directory? applicationSupportDirectory = await getApplicationSupportDirectory(); |
||||
Directory? tempDirectory = await getTemporaryDirectory(); |
||||
Directory? pathApplicationDocumentsPath = await getApplicationDocumentsDirectory(); |
||||
Directory? pathDownloadsPath = await getDownloadsDirectory(); |
||||
List<Directory>? pathPictures = await getExternalStorageDirectories(type: StorageDirectory.pictures); |
||||
List<Directory>? pathMusic = await getExternalStorageDirectories(type: StorageDirectory.music); |
||||
List<Directory>? pathMovies = await getExternalStorageDirectories(type: StorageDirectory.movies); |
||||
|
||||
// Update state variable |
||||
setState(() { |
||||
_applicationOrg = applicationOrg; |
||||
_applicationName = applicationName; |
||||
|
||||
_pathApplicationSupportDirectory = applicationSupportDirectory.path; |
||||
_pathTempDirectory = tempDirectory.path; |
||||
_pathApplicationDocumentsPath = pathApplicationDocumentsPath.path; |
||||
_pathDownloadsPath = pathDownloadsPath?.path; |
||||
_pathPictures = pathPictures?.first.path; |
||||
_pathMusic = pathMusic?.first.path; |
||||
_pathMovies = pathMovies?.first.path; |
||||
}); |
||||
} on Exception catch (e) { |
||||
setState(() { |
||||
_error = e.toString(); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
const textStyleWhite = TextStyle(fontSize: 18, color: Colors.white); |
||||
const textStyleTitle = TextStyle(fontSize: 20, color: Colors.black); |
||||
const textStylePath = TextStyle(fontSize: 18, color: Colors.black54); |
||||
|
||||
const spaceMedium = SizedBox(height: 20); |
||||
const spaceSmall = SizedBox(height: 10); |
||||
|
||||
return MaterialApp( |
||||
home: Scaffold( |
||||
appBar: AppBar( |
||||
title: const Text('Example path_provider'), |
||||
), |
||||
body: Stack( |
||||
children: [ |
||||
// Error message |
||||
Visibility( |
||||
visible: _error != null, |
||||
child: Center( |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(16), |
||||
child: Container( |
||||
padding: const EdgeInsets.all(20), |
||||
decoration: const BoxDecoration( |
||||
color: Colors.redAccent, |
||||
borderRadius: BorderRadius.all(Radius.circular(10.0)), |
||||
), |
||||
child: Text( |
||||
_error ?? '', |
||||
style: textStyleWhite, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
), |
||||
// List directories path |
||||
Visibility( |
||||
visible: _error == null, |
||||
child: SingleChildScrollView( |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(16), |
||||
child: Center( |
||||
child: Column( |
||||
children: [ |
||||
// Info |
||||
Container( |
||||
padding: const EdgeInsets.all(20), |
||||
decoration: const BoxDecoration( |
||||
color: Colors.green, |
||||
borderRadius: BorderRadius.all(Radius.circular(10.0)), |
||||
), |
||||
child: const Text( |
||||
'Demo application demonstration implementation of path_provider', |
||||
style: textStyleWhite, |
||||
textAlign: TextAlign.center, |
||||
), |
||||
), |
||||
const SizedBox(height: 30), |
||||
|
||||
// ApplicationOrg |
||||
const Text( |
||||
'Application Org', |
||||
style: textStyleTitle, |
||||
), |
||||
spaceSmall, |
||||
Text( |
||||
_applicationOrg ?? 'Not found.', |
||||
style: textStylePath, |
||||
), |
||||
|
||||
spaceMedium, |
||||
// ApplicationName |
||||
const Text( |
||||
'Application Name', |
||||
style: textStyleTitle, |
||||
), |
||||
spaceSmall, |
||||
Text( |
||||
_applicationName ?? 'Not found.', |
||||
style: textStylePath, |
||||
), |
||||
|
||||
spaceMedium, |
||||
// TempDirectory |
||||
const Text( |
||||
'ApplicationSupportDirectory', |
||||
style: textStyleTitle, |
||||
), |
||||
spaceSmall, |
||||
Text( |
||||
_pathApplicationSupportDirectory ?? 'Not found.', |
||||
style: textStylePath, |
||||
), |
||||
|
||||
spaceMedium, |
||||
// TempDirectory |
||||
const Text( |
||||
'TempDirectory', |
||||
style: textStyleTitle, |
||||
), |
||||
spaceSmall, |
||||
Text( |
||||
_pathTempDirectory ?? 'Not found.', |
||||
style: textStylePath, |
||||
), |
||||
spaceMedium, |
||||
|
||||
// ApplicationDocumentsPath |
||||
const Text( |
||||
'ApplicationDocumentsPath', |
||||
style: textStyleTitle, |
||||
), |
||||
spaceSmall, |
||||
Text( |
||||
_pathApplicationDocumentsPath ?? 'Not found.', |
||||
style: textStylePath, |
||||
), |
||||
spaceMedium, |
||||
|
||||
// DownloadsPath |
||||
const Text( |
||||
'DownloadsPath', |
||||
style: textStyleTitle, |
||||
), |
||||
spaceSmall, |
||||
Text( |
||||
_pathDownloadsPath ?? 'Not found.', |
||||
style: textStylePath, |
||||
), |
||||
spaceMedium, |
||||
|
||||
// Pictures |
||||
const Text( |
||||
'Pictures', |
||||
style: textStyleTitle, |
||||
), |
||||
spaceSmall, |
||||
Text( |
||||
_pathPictures ?? 'Not found.', |
||||
style: textStylePath, |
||||
), |
||||
spaceMedium, |
||||
|
||||
// Music |
||||
const Text( |
||||
'Music', |
||||
style: textStyleTitle, |
||||
), |
||||
spaceSmall, |
||||
Text( |
||||
_pathMusic ?? 'Not found.', |
||||
style: textStylePath, |
||||
), |
||||
spaceMedium, |
||||
|
||||
// Movies |
||||
const Text( |
||||
'Movies', |
||||
style: textStyleTitle, |
||||
), |
||||
spaceSmall, |
||||
Text( |
||||
_pathMovies ?? 'Not found.', |
||||
style: textStylePath, |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,266 @@
|
||||
# Generated by pub |
||||
# See https://dart.dev/tools/pub/glossary#lockfile |
||||
packages: |
||||
async: |
||||
dependency: transitive |
||||
description: |
||||
name: async |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.9.0" |
||||
boolean_selector: |
||||
dependency: transitive |
||||
description: |
||||
name: boolean_selector |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.0" |
||||
characters: |
||||
dependency: transitive |
||||
description: |
||||
name: characters |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.2.1" |
||||
clock: |
||||
dependency: transitive |
||||
description: |
||||
name: clock |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.1.1" |
||||
collection: |
||||
dependency: transitive |
||||
description: |
||||
name: collection |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.16.0" |
||||
cupertino_icons: |
||||
dependency: "direct main" |
||||
description: |
||||
name: cupertino_icons |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.0.5" |
||||
fake_async: |
||||
dependency: transitive |
||||
description: |
||||
name: fake_async |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.3.1" |
||||
ffi: |
||||
dependency: transitive |
||||
description: |
||||
name: ffi |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.2.1" |
||||
file: |
||||
dependency: transitive |
||||
description: |
||||
name: file |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "6.1.4" |
||||
flutter: |
||||
dependency: "direct main" |
||||
description: flutter |
||||
source: sdk |
||||
version: "0.0.0" |
||||
flutter_lints: |
||||
dependency: "direct dev" |
||||
description: |
||||
name: flutter_lints |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.0.1" |
||||
flutter_test: |
||||
dependency: "direct dev" |
||||
description: flutter |
||||
source: sdk |
||||
version: "0.0.0" |
||||
lints: |
||||
dependency: transitive |
||||
description: |
||||
name: lints |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.0.1" |
||||
matcher: |
||||
dependency: transitive |
||||
description: |
||||
name: matcher |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.12.12" |
||||
material_color_utilities: |
||||
dependency: transitive |
||||
description: |
||||
name: material_color_utilities |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.1.5" |
||||
meta: |
||||
dependency: transitive |
||||
description: |
||||
name: meta |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.8.0" |
||||
path: |
||||
dependency: transitive |
||||
description: |
||||
name: path |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.8.2" |
||||
path_provider: |
||||
dependency: "direct main" |
||||
description: |
||||
name: path_provider |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.0.14" |
||||
path_provider_android: |
||||
dependency: transitive |
||||
description: |
||||
name: path_provider_android |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.0.26" |
||||
path_provider_aurora: |
||||
dependency: "direct main" |
||||
description: |
||||
path: ".." |
||||
relative: true |
||||
source: path |
||||
version: "0.0.1" |
||||
path_provider_foundation: |
||||
dependency: transitive |
||||
description: |
||||
name: path_provider_foundation |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.2.2" |
||||
path_provider_linux: |
||||
dependency: transitive |
||||
description: |
||||
name: path_provider_linux |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.10" |
||||
path_provider_platform_interface: |
||||
dependency: transitive |
||||
description: |
||||
name: path_provider_platform_interface |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.0.6" |
||||
path_provider_windows: |
||||
dependency: transitive |
||||
description: |
||||
name: path_provider_windows |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.0.7" |
||||
platform: |
||||
dependency: transitive |
||||
description: |
||||
name: platform |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "3.1.0" |
||||
plugin_platform_interface: |
||||
dependency: transitive |
||||
description: |
||||
name: plugin_platform_interface |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.4" |
||||
process: |
||||
dependency: transitive |
||||
description: |
||||
name: process |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "4.2.4" |
||||
sky_engine: |
||||
dependency: transitive |
||||
description: flutter |
||||
source: sdk |
||||
version: "0.0.99" |
||||
source_span: |
||||
dependency: transitive |
||||
description: |
||||
name: source_span |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.9.0" |
||||
stack_trace: |
||||
dependency: transitive |
||||
description: |
||||
name: stack_trace |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.10.0" |
||||
stream_channel: |
||||
dependency: transitive |
||||
description: |
||||
name: stream_channel |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.0" |
||||
string_scanner: |
||||
dependency: transitive |
||||
description: |
||||
name: string_scanner |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.1.1" |
||||
term_glyph: |
||||
dependency: transitive |
||||
description: |
||||
name: term_glyph |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.2.1" |
||||
test_api: |
||||
dependency: transitive |
||||
description: |
||||
name: test_api |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.4.12" |
||||
vector_math: |
||||
dependency: transitive |
||||
description: |
||||
name: vector_math |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.2" |
||||
win32: |
||||
dependency: transitive |
||||
description: |
||||
name: win32 |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.6.1" |
||||
xdg_directories: |
||||
dependency: transitive |
||||
description: |
||||
name: xdg_directories |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.0.0" |
||||
xdga_directories: |
||||
dependency: transitive |
||||
description: |
||||
path: "../../../xdga_directories" |
||||
relative: false |
||||
source: path |
||||
version: "0.0.1" |
||||
sdks: |
||||
dart: ">=2.18.6 <3.0.0" |
||||
flutter: ">=3.3.0" |
@ -0,0 +1,85 @@
|
||||
name: path_provider_aurora_example |
||||
description: Demonstrates how to use the path_provider_aurora plugin. |
||||
|
||||
# The following line prevents the package from being accidentally published to |
||||
# pub.dev using `flutter pub publish`. This is preferred for private packages. |
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev |
||||
|
||||
environment: |
||||
sdk: '>=2.18.6 <3.0.0' |
||||
|
||||
# Dependencies specify other packages that your package needs in order to work. |
||||
# To automatically upgrade your package dependencies to the latest versions |
||||
# consider running `flutter pub upgrade --major-versions`. Alternatively, |
||||
# dependencies can be manually updated by changing the version numbers below to |
||||
# the latest version available on pub.dev. To see which dependencies have newer |
||||
# versions available, run `flutter pub outdated`. |
||||
dependencies: |
||||
flutter: |
||||
sdk: flutter |
||||
|
||||
path_provider: ^2.0.7 |
||||
path_provider_aurora: |
||||
# When depending on this package from a real application you should use: |
||||
# path_provider_aurora: ^x.y.z |
||||
# See https://dart.dev/tools/pub/dependencies#version-constraints |
||||
# The example app is bundled with the plugin so we use a path dependency on |
||||
# the parent directory to use the current plugin's version. |
||||
path: ../ |
||||
|
||||
# The following adds the Cupertino Icons font to your application. |
||||
# Use with the CupertinoIcons class for iOS style icons. |
||||
cupertino_icons: ^1.0.2 |
||||
|
||||
dev_dependencies: |
||||
flutter_test: |
||||
sdk: flutter |
||||
|
||||
# The "flutter_lints" package below contains a set of recommended lints to |
||||
# encourage good coding practices. The lint set provided by the package is |
||||
# activated in the `analysis_options.yaml` file located at the root of your |
||||
# package. See that file for information about deactivating specific lint |
||||
# rules and activating additional ones. |
||||
flutter_lints: ^2.0.0 |
||||
|
||||
# For information on the generic Dart part of this file, see the |
||||
# following page: https://dart.dev/tools/pub/pubspec |
||||
|
||||
# The following section is specific to Flutter packages. |
||||
flutter: |
||||
|
||||
# The following line ensures that the Material Icons font is |
||||
# included with your application, so that you can use the icons in |
||||
# the material Icons class. |
||||
uses-material-design: true |
||||
|
||||
# To add assets to your application, add an assets section, like this: |
||||
# assets: |
||||
# - images/a_dot_burr.jpeg |
||||
# - images/a_dot_ham.jpeg |
||||
|
||||
# An image asset can refer to one or more resolution-specific "variants", see |
||||
# https://flutter.dev/assets-and-images/#resolution-aware |
||||
|
||||
# For details regarding adding assets from package dependencies, see |
||||
# https://flutter.dev/assets-and-images/#from-packages |
||||
|
||||
# To add custom fonts to your application, add a fonts section here, |
||||
# in this "flutter" section. Each entry in this list should have a |
||||
# "family" key with the font family name, and a "fonts" key with a |
||||
# list giving the asset and other descriptors for the font. For |
||||
# example: |
||||
# fonts: |
||||
# - family: Schyler |
||||
# fonts: |
||||
# - asset: fonts/Schyler-Regular.ttf |
||||
# - asset: fonts/Schyler-Italic.ttf |
||||
# style: italic |
||||
# - family: Trajan Pro |
||||
# fonts: |
||||
# - asset: fonts/TrajanPro.ttf |
||||
# - asset: fonts/TrajanPro_Bold.ttf |
||||
# weight: 700 |
||||
# |
||||
# For details regarding fonts from package dependencies, |
||||
# see https://flutter.dev/custom-fonts/#from-packages |
@ -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:path_provider_aurora_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, |
||||
); |
||||
}); |
||||
} |
@ -0,0 +1,81 @@
|
||||
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; |
||||
import 'package:xdga_directories/xdga_directories.dart' as xdga_directories; |
||||
import 'package:path/path.dart' as p; |
||||
|
||||
import 'path_provider_aurora_platform_interface.dart'; |
||||
|
||||
/// The aurora implementation of [PathProviderPlatform] |
||||
/// |
||||
/// This class implements the `package:path_provider` functionality for Aurora. |
||||
class PathProviderAurora extends PathProviderPlatform { |
||||
/// Registers this class as the default instance of [PathProviderPlatform] |
||||
static void registerWith() { |
||||
PathProviderPlatform.instance = PathProviderAurora(); |
||||
} |
||||
|
||||
/// Get application name |
||||
static Future<String?> getApplicationName() { |
||||
return PathProviderAuroraPlatform.instance.getApplicationName(); |
||||
} |
||||
|
||||
/// Get application org |
||||
static Future<String?> getApplicationOrg() { |
||||
return PathProviderAuroraPlatform.instance.getApplicationOrg(); |
||||
} |
||||
|
||||
/// Path to a directory where the application may place application support files. |
||||
@override |
||||
Future<String?> getApplicationSupportPath() async { |
||||
String? org = await getApplicationOrg(); |
||||
String? name = await getApplicationName(); |
||||
// QStandardPaths::AppDataLocation |
||||
return p.join(xdga_directories.getAppDataLocation(), org, name); |
||||
} |
||||
|
||||
/// Path to the temporary directory on the device that is not backed up and is |
||||
/// suitable for storing caches of downloaded files. |
||||
@override |
||||
Future<String> getTemporaryPath() async { |
||||
String? org = await getApplicationOrg(); |
||||
String? name = await getApplicationName(); |
||||
// QStandardPaths::CacheLocation |
||||
return p.join(xdga_directories.getCacheLocation(), org, name); |
||||
} |
||||
|
||||
/// Path to a directory where the application may place data that is |
||||
/// user-generated, or that cannot otherwise be recreated by your application. |
||||
@override |
||||
Future<String> getApplicationDocumentsPath() async { |
||||
// QStandardPaths::DocumentsLocation |
||||
return xdga_directories.getDocumentsLocation(); |
||||
} |
||||
|
||||
/// Path to the directory where downloaded files can be stored. |
||||
/// This is typically only relevant on desktop operating systems. |
||||
@override |
||||
Future<String> getDownloadsPath() async { |
||||
// QStandardPaths::DownloadLocation |
||||
return xdga_directories.getDownloadLocation(); |
||||
} |
||||
|
||||
/// Paths to directories where application specific data can be stored. |
||||
/// These paths typically reside on external storage like separate partitions |
||||
/// or SD cards. Phones may have multiple storage directories available. |
||||
@override |
||||
Future<List<String>?> getExternalStoragePaths({ |
||||
/// Optional parameter. See [StorageDirectory] for more informations on |
||||
/// how this type translates to Android storage directories. |
||||
StorageDirectory? type, |
||||
}) async { |
||||
switch (type) { |
||||
case StorageDirectory.pictures: |
||||
return [xdga_directories.getPicturesLocation()]; // QStandardPaths::PicturesLocation |
||||
case StorageDirectory.music: |
||||
return [xdga_directories.getMusicLocation()]; // QStandardPaths::MusicLocation |
||||
case StorageDirectory.movies: |
||||
return [xdga_directories.getMoviesLocation()]; // QStandardPaths::MoviesLocation |
||||
default: |
||||
throw UnimplementedError('Type "$type" not supported.'); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,21 @@
|
||||
import 'package:flutter/foundation.dart'; |
||||
import 'package:flutter/services.dart'; |
||||
|
||||
import 'path_provider_aurora_platform_interface.dart'; |
||||
|
||||
/// An implementation of [PathProviderAuroraPlatform] that uses method channels. |
||||
class MethodChannelPathProviderAurora extends PathProviderAuroraPlatform { |
||||
/// The method channel used to interact with the native platform. |
||||
@visibleForTesting |
||||
final methodChannel = const MethodChannel('path_provider_aurora'); |
||||
|
||||
@override |
||||
Future<String?> getApplicationOrg() async { |
||||
return await methodChannel.invokeMethod<String>('getApplicationOrg'); |
||||
} |
||||
|
||||
@override |
||||
Future<String?> getApplicationName() async { |
||||
return await methodChannel.invokeMethod<String>('getApplicationName'); |
||||
} |
||||
} |
@ -0,0 +1,33 @@
|
||||
import 'package:plugin_platform_interface/plugin_platform_interface.dart'; |
||||
|
||||
import 'path_provider_aurora_method_channel.dart'; |
||||
|
||||
abstract class PathProviderAuroraPlatform extends PlatformInterface { |
||||
/// Constructs a PathProviderAuroraPlatform. |
||||
PathProviderAuroraPlatform() : super(token: _token); |
||||
|
||||
static final Object _token = Object(); |
||||
|
||||
static PathProviderAuroraPlatform _instance = MethodChannelPathProviderAurora(); |
||||
|
||||
/// The default instance of [PathProviderAuroraPlatform] to use. |
||||
/// |
||||
/// Defaults to [MethodChannelPathProviderAurora]. |
||||
static PathProviderAuroraPlatform get instance => _instance; |
||||
|
||||
/// Platform-specific implementations should set this with their own |
||||
/// platform-specific class that extends [PathProviderAuroraPlatform] when |
||||
/// they register themselves. |
||||
static set instance(PathProviderAuroraPlatform instance) { |
||||
PlatformInterface.verifyToken(instance, _token); |
||||
_instance = instance; |
||||
} |
||||
|
||||
Future<String?> getApplicationOrg() { |
||||
throw UnimplementedError('getApplicationOrg() has not been implemented.'); |
||||
} |
||||
|
||||
Future<String?> getApplicationName() { |
||||
throw UnimplementedError('getApplicationName() has not been implemented.'); |
||||
} |
||||
} |
@ -0,0 +1,32 @@
|
||||
name: path_provider_aurora |
||||
description: The Aurora OS implementation of path_provider. |
||||
version: 0.0.1 |
||||
homepage: https://os-git.omprussia.ru/non-oss/flutter/flutter-plugins/packages/xdga_directories |
||||
|
||||
environment: |
||||
sdk: '>=2.18.6 <3.0.0' |
||||
flutter: ">=2.5.0" |
||||
|
||||
flutter: |
||||
plugin: |
||||
implements: path_provider |
||||
platforms: |
||||
aurora: |
||||
dartPluginClass: PathProviderAurora |
||||
pluginClass: PathProviderAuroraPlugin |
||||
|
||||
dependencies: |
||||
flutter: |
||||
sdk: flutter |
||||
path: ^1.8.2 |
||||
plugin_platform_interface: ^2.0.2 |
||||
path_provider_platform_interface: ^2.0.6 |
||||
xdga_directories: |
||||
path: ../../xdga_directories |
||||
|
||||
dev_dependencies: |
||||
flutter_test: |
||||
sdk: flutter |
||||
flutter_lints: ^2.0.0 |
||||
|
||||
|
@ -0,0 +1,34 @@
|
||||
import 'package:flutter/services.dart'; |
||||
import 'package:flutter_test/flutter_test.dart'; |
||||
import 'package:path_provider_aurora/path_provider_aurora_method_channel.dart'; |
||||
|
||||
void main() { |
||||
MethodChannelPathProviderAurora platform = MethodChannelPathProviderAurora(); |
||||
const MethodChannel channel = MethodChannel('path_provider_aurora'); |
||||
|
||||
TestWidgetsFlutterBinding.ensureInitialized(); |
||||
|
||||
setUp(() { |
||||
channel.setMockMethodCallHandler((MethodCall methodCall) async { |
||||
switch (methodCall.method) { |
||||
case 'getApplicationOrg': |
||||
return 'com.example'; |
||||
case 'getApplicationName': |
||||
return 'path_provider_aurora'; |
||||
} |
||||
return ''; |
||||
}); |
||||
}); |
||||
|
||||
tearDown(() { |
||||
channel.setMockMethodCallHandler(null); |
||||
}); |
||||
|
||||
test('onGetApplicationOrg', () async { |
||||
expect(await platform.getApplicationOrg(), 'com.example'); |
||||
}); |
||||
|
||||
test('onGetApplicationName', () async { |
||||
expect(await platform.getApplicationName(), 'path_provider_aurora'); |
||||
}); |
||||
} |
@ -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/ |
@ -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: unknown |
||||
|
||||
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' |
@ -0,0 +1,17 @@
|
||||
# shared_preferences_aurora |
||||
|
||||
The Aurora implementation of [`shared_preferences`][https://pub.dev/packages/shared_preferences]. |
||||
|
||||
## Usage |
||||
This package is not an _endorsed_ implementation of `shared_preferences`. |
||||
Therefore, you have to include `path_provider_aurora` alongside `shared_preferences` as dependencies in your `pubspec.yaml` file. |
||||
|
||||
```yaml |
||||
dependencies: |
||||
shared_preferences: ^2.1.1 |
||||
shared_preferences_aurora: ^0.0.0 # @todo Not published |
||||
``` |
||||
|
||||
### Preview example |
||||
|
||||
 |
@ -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 |
@ -0,0 +1,25 @@
|
||||
cmake_minimum_required(VERSION 3.10) |
||||
|
||||
set(PROJECT_NAME shared_preferences_aurora) |
||||
set(PLUGIN_NAME shared_preferences_aurora_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") |
||||
|
||||
find_package(PkgConfig REQUIRED) |
||||
pkg_check_modules(FlutterEmbedder REQUIRED IMPORTED_TARGET flutter-embedder) |
||||
pkg_check_modules(Qt5Core REQUIRED IMPORTED_TARGET Qt5Core) |
||||
|
||||
add_library(${PLUGIN_NAME} SHARED shared_preferences_aurora_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 PkgConfig::Qt5Core) |
||||
|
||||
target_include_directories(${PLUGIN_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) |
||||
target_compile_definitions(${PLUGIN_NAME} PRIVATE PLUGIN_IMPL) |
@ -0,0 +1,66 @@
|
||||
#ifndef FLUTTER_PLUGIN_SHARED_PREFERENCES_AURORA_PLUGIN_H |
||||
#define FLUTTER_PLUGIN_SHARED_PREFERENCES_AURORA_PLUGIN_H |
||||
|
||||
#include <flutter/plugin-interface.h> |
||||
#include <flutter/method-channel.h> |
||||
#include <QSettings> |
||||
#include <QString> |
||||
|
||||
#ifdef PLUGIN_IMPL |
||||
#define PLUGIN_EXPORT __attribute__((visibility("default"))) |
||||
#else |
||||
#define PLUGIN_EXPORT |
||||
#endif |
||||
|
||||
class PLUGIN_EXPORT SharedPreferencesAuroraPlugin final : public PluginInterface |
||||
{ |
||||
public: |
||||
SharedPreferencesAuroraPlugin(); |
||||
void RegisterWithRegistrar(PluginRegistrar ®istrar) override; |
||||
|
||||
struct ARGS |
||||
{ |
||||
QString prefix; |
||||
QString key; |
||||
Encodable value; |
||||
}; |
||||
|
||||
enum Types |
||||
{
|
||||
Int, |
||||
Bool, |
||||
Double, |
||||
String, |
||||
List |
||||
}; |
||||
|
||||
enum Methods
|
||||
{
|
||||
setInt, |
||||
setBool, |
||||
setDouble, |
||||
setString, |
||||
setStringList, |
||||
clearWithPrefix, |
||||
remove, |
||||
getAllWithPrefix, |
||||
}; |
||||
|
||||
private: |
||||
void onMethodCall(const MethodCall &call); |
||||
void unimplemented(const MethodCall &call); |
||||
ARGS getArguments(const MethodCall &call); |
||||
void onSetInt(const MethodCall &call); |
||||
void onSetBool(const MethodCall &call); |
||||
void onSetDouble(const MethodCall &call); |
||||
void onSetString(const MethodCall &call); |
||||
void onSetStringList(const MethodCall &call); |
||||
void onClearWithPrefix(const MethodCall &call); |
||||
void onRemove(const MethodCall &call); |
||||
void onGetAllWithPrefix(const MethodCall &call); |
||||
|
||||
QSettings settings; |
||||
std::map <std::string, int> mapping; |
||||
}; |
||||
|
||||
#endif /* FLUTTER_PLUGIN_SHARED_PREFERENCES_AURORA_PLUGIN_H */ |
@ -0,0 +1,256 @@
|
||||
#include <shared_preferences_aurora/shared_preferences_aurora_plugin.h> |
||||
#include <flutter/method-channel.h> |
||||
#include <flutter/application.h> |
||||
#include <QSettings> |
||||
#include <QVariant> |
||||
#include <QDir> |
||||
|
||||
namespace { |
||||
|
||||
QString defaultSettingsFile() |
||||
{ |
||||
const auto [orgname, appname] = Application::GetID(); |
||||
|
||||
return QStringLiteral("%1/.local/share/%2/%3/.flutter_shared_preferences.conf") |
||||
.arg(QDir::homePath()) |
||||
.arg(QString::fromStdString(orgname)) |
||||
.arg(QString::fromStdString(appname)); |
||||
} |
||||
|
||||
} /* namespace */ |
||||
|
||||
SharedPreferencesAuroraPlugin::SharedPreferencesAuroraPlugin(): settings( |
||||
defaultSettingsFile(), |
||||
QSettings::NativeFormat |
||||
) { |
||||
// map methods
|
||||
this->mapping = std::map <std::string, int>({ |
||||
{"setInt", Methods::setInt}, |
||||
{"setBool", Methods::setBool}, |
||||
{"setDouble", Methods::setDouble}, |
||||
{"setString", Methods::setString}, |
||||
{"setStringList", Methods::setStringList}, |
||||
{"clearWithPrefix", Methods::clearWithPrefix}, |
||||
{"remove", Methods::remove}, |
||||
{"getAllWithPrefix", Methods::getAllWithPrefix}, |
||||
}); |
||||
} |
||||
|
||||
void SharedPreferencesAuroraPlugin::RegisterWithRegistrar(PluginRegistrar ®istrar) |
||||
{ |
||||
registrar.RegisterMethodChannel("shared_preferences_aurora", |
||||
MethodCodecType::Standard, |
||||
[this](const MethodCall &call) { this->onMethodCall(call); }); |
||||
} |
||||
|
||||
SharedPreferencesAuroraPlugin::ARGS SharedPreferencesAuroraPlugin::getArguments(const MethodCall &call) |
||||
{ |
||||
QString key = QString::fromStdString(call.GetArguments()["key"].GetString()); |
||||
Encodable value = call.GetArguments()["value"]; |
||||
ARGS args; |
||||
|
||||
args.prefix = key.split('.').first(); |
||||
args.key = key.mid(args.prefix.length() + 1, key.length()); |
||||
args.value = value; |
||||
|
||||
return args; |
||||
} |
||||
|
||||
void SharedPreferencesAuroraPlugin::onMethodCall(const MethodCall &call) |
||||
{ |
||||
const auto &method = call.GetMethod(); |
||||
|
||||
switch (this->mapping[method])
|
||||
{ |
||||
case Methods::setInt:
|
||||
onSetInt(call);
|
||||
return; |
||||
case Methods::setBool:
|
||||
onSetBool(call);
|
||||
return; |
||||
case Methods::setDouble:
|
||||
onSetDouble(call);
|
||||
return; |
||||
case Methods::setString:
|
||||
onSetString(call);
|
||||
return; |
||||
case Methods::setStringList:
|
||||
onSetStringList(call);
|
||||
return; |
||||
case Methods::clearWithPrefix:
|
||||
onClearWithPrefix(call);
|
||||
return; |
||||
case Methods::remove:
|
||||
onRemove(call);
|
||||
return; |
||||
case Methods::getAllWithPrefix:
|
||||
onGetAllWithPrefix(call);
|
||||
return; |
||||
} |
||||
|
||||
unimplemented(call); |
||||
} |
||||
|
||||
void SharedPreferencesAuroraPlugin::onSetInt(const MethodCall &call) |
||||
{ |
||||
const auto [prefix, key, value] = this->getArguments(call); |
||||
|
||||
settings.beginGroup(prefix); |
||||
settings.setValue( |
||||
QStringLiteral("%1:").arg(Types::Int) + key,
|
||||
value.GetInt() |
||||
); |
||||
settings.sync(); |
||||
settings.endGroup(); |
||||
|
||||
call.SendSuccessResponse(true); |
||||
} |
||||
|
||||
void SharedPreferencesAuroraPlugin::onSetBool(const MethodCall &call) |
||||
{ |
||||
const auto [prefix, key, value] = this->getArguments(call); |
||||
|
||||
settings.beginGroup(prefix); |
||||
settings.setValue( |
||||
QStringLiteral("%1:").arg(Types::Bool) + key,
|
||||
value.GetBoolean() |
||||
); |
||||
settings.sync(); |
||||
settings.endGroup(); |
||||
|
||||
call.SendSuccessResponse(true); |
||||
} |
||||
|
||||
void SharedPreferencesAuroraPlugin::onSetDouble(const MethodCall &call) |
||||
{ |
||||
const auto [prefix, key, value] = this->getArguments(call); |
||||
|
||||
settings.beginGroup(prefix); |
||||
settings.setValue( |
||||
QStringLiteral("%1:").arg(Types::Double) + key,
|
||||
value.GetFloat() |
||||
); |
||||
settings.sync(); |
||||
settings.endGroup(); |
||||
|
||||
call.SendSuccessResponse(true); |
||||
} |
||||
|
||||
void SharedPreferencesAuroraPlugin::onSetString(const MethodCall &call) |
||||
{ |
||||
const auto [prefix, key, value] = this->getArguments(call); |
||||
|
||||
settings.beginGroup(prefix); |
||||
settings.setValue( |
||||
QStringLiteral("%1:").arg(Types::String) + key,
|
||||
QString::fromStdString(value.GetString()) |
||||
); |
||||
settings.sync(); |
||||
settings.endGroup(); |
||||
|
||||
call.SendSuccessResponse(true); |
||||
} |
||||
|
||||
void SharedPreferencesAuroraPlugin::onSetStringList(const MethodCall &call) |
||||
{ |
||||
const auto [prefix, key, value] = this->getArguments(call); |
||||
const auto vec = value.GetList(); |
||||
|
||||
QStringList strings; |
||||
|
||||
for (const auto& item : vec) |
||||
{ |
||||
strings.append(QString::fromStdString(item.GetString())); |
||||
} |
||||
|
||||
settings.beginGroup(prefix); |
||||
settings.setValue( |
||||
QStringLiteral("%1:").arg(Types::List) + key,
|
||||
strings |
||||
); |
||||
settings.sync(); |
||||
settings.endGroup(); |
||||
call.SendSuccessResponse(true); |
||||
} |
||||
|
||||
void SharedPreferencesAuroraPlugin::onClearWithPrefix(const MethodCall &call) |
||||
{ |
||||
const auto prefix = QString::fromStdString(call.GetArguments()["prefix"].GetString()) |
||||
.replace(".", ""); |
||||
|
||||
settings.beginGroup(prefix); |
||||
settings.remove(""); |
||||
settings.sync(); |
||||
settings.endGroup(); |
||||
|
||||
call.SendSuccessResponse(true); |
||||
} |
||||
|
||||
void SharedPreferencesAuroraPlugin::onRemove(const MethodCall &call) |
||||
{ |
||||
QString raw = QString::fromStdString(call.GetArguments()["key"].GetString()); |
||||
|
||||
const auto prefix = raw.split('.').first(); |
||||
const auto key = raw.mid(prefix.length() + 1, raw.length()); |
||||
|
||||
settings.beginGroup(prefix); |
||||
settings.remove(QStringLiteral("%1:").arg(Types::Int) + key); |
||||
settings.remove(QStringLiteral("%1:").arg(Types::Bool) + key); |
||||
settings.remove(QStringLiteral("%1:").arg(Types::Double) + key); |
||||
settings.remove(QStringLiteral("%1:").arg(Types::String) + key); |
||||
settings.remove(QStringLiteral("%1:").arg(Types::List) + key); |
||||
settings.sync(); |
||||
settings.endGroup(); |
||||
|
||||
call.SendSuccessResponse(true); |
||||
} |
||||
|
||||
void SharedPreferencesAuroraPlugin::onGetAllWithPrefix(const MethodCall &call) |
||||
{ |
||||
const auto prefix = QString::fromStdString(call.GetArguments()["prefix"].GetString()) |
||||
.replace(".", ""); |
||||
|
||||
std::map<Encodable, Encodable> map; |
||||
|
||||
settings.beginGroup(prefix); |
||||
|
||||
for (const auto& item : settings.allKeys()) |
||||
{ |
||||
const auto type = item.split(":").first(); |
||||
const auto key = prefix + "." + item.mid(type.length() + 1, item.length()); |
||||
const auto variant = settings.value(item); |
||||
|
||||
switch (type.toInt()) |
||||
{ |
||||
case Types::Int: |
||||
map[key.toStdString()] = Encodable(variant.toInt()); |
||||
break; |
||||
case Types::Bool: |
||||
map[key.toStdString()] = Encodable(variant.toBool()); |
||||
break; |
||||
case Types::Double: |
||||
map[key.toStdString()] = Encodable(variant.toDouble()); |
||||
break; |
||||
case Types::String: |
||||
map[key.toStdString()] = Encodable(variant.toString().toStdString()); |
||||
break; |
||||
case Types::List: |
||||
std::vector<Encodable> vec; |
||||
QStringList list = variant.toStringList(); |
||||
for (const auto& item : list) |
||||
{ |
||||
vec.push_back(item.toStdString()); |
||||
} |
||||
map[key.toStdString()] = vec; |
||||
} |
||||
} |
||||
|
||||
settings.endGroup(); |
||||
|
||||
call.SendSuccessResponse(map); |
||||
} |
||||
|
||||
void SharedPreferencesAuroraPlugin::unimplemented(const MethodCall &call) |
||||
{ |
||||
call.SendSuccessResponse(nullptr); |
||||
} |
After Width: | Height: | Size: 91 KiB |
@ -0,0 +1,44 @@
|
||||
# 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/ |
||||
|
||||
# Symbolication related |
||||
app.*.symbols |
||||
|
||||
# Obfuscation related |
||||
app.*.map.json |
||||
|
||||
# Android Studio will place build artifacts here |
||||
/android/app/debug |
||||
/android/app/profile |
||||
/android/app/release |
@ -0,0 +1,16 @@
|
||||
# shared_preferences_aurora_example |
||||
|
||||
Demonstrates how to use the shared_preferences_aurora 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. |
@ -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 |
@ -0,0 +1 @@
|
||||
flutter/ephemeral |
@ -0,0 +1,47 @@
|
||||
cmake_minimum_required(VERSION 3.10) |
||||
project(com.example.shared_preferences_aurora_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) |
@ -0,0 +1,12 @@
|
||||
[Desktop Entry] |
||||
Type=Application |
||||
Name=shared_preferences_aurora_example |
||||
Comment=Demonstrates how to use the shared_preferences_aurora plugin. |
||||
Icon=com.example.shared_preferences_aurora_example |
||||
Exec=/usr/bin/com.example.shared_preferences_aurora_example |
||||
X-Nemo-Application-Type=silica-qt5 |
||||
|
||||
[X-Application] |
||||
Permissions= |
||||
OrganizationName=com.example |
||||
ApplicationName=shared_preferences_aurora_example |
@ -0,0 +1,16 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include <flutter/application.h> |
||||
#include <shared_preferences_aurora/shared_preferences_aurora_plugin.h> |
||||
|
||||
#include "generated_plugin_registrant.h" |
||||
|
||||
void RegisterPlugins() { |
||||
Application::RegisterPlugins({ |
||||
std::make_shared<SharedPreferencesAuroraPlugin>(), |
||||
}); |
||||
} |
@ -0,0 +1,12 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifndef GENERATED_PLUGIN_REGISTRANT |
||||
#define GENERATED_PLUGIN_REGISTRANT |
||||
|
||||
void RegisterPlugins(); |
||||
|
||||
#endif /* GENERATED_PLUGIN_REGISTRANT */ |
@ -0,0 +1,31 @@
|
||||
# |
||||
# Generated file, do not edit. |
||||
# |
||||
set(ROOT_PROJECT_BINARY_DIR "${PROJECT_BINARY_DIR}") |
||||
|
||||
function(add_library TARGET) |
||||
_add_library(${TARGET} ${ARGN}) |
||||
|
||||
if(NOT "${TARGET}" MATCHES "^PkgConfig::.*") |
||||
add_custom_command(TARGET ${TARGET} POST_BUILD |
||||
COMMAND ${CMAKE_COMMAND} -E copy |
||||
"$<TARGET_FILE:${TARGET}>" |
||||
"${ROOT_PROJECT_BINARY_DIR}/bundle/lib/$<TARGET_FILE_NAME:${TARGET}>") |
||||
endif(NOT "${TARGET}" MATCHES "^PkgConfig::.*") |
||||
endfunction() |
||||
|
||||
list(APPEND FLUTTER_PLATFORM_PLUGIN_LIST |
||||
shared_preferences_aurora |
||||
) |
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST |
||||
) |
||||
|
||||
foreach(PLUGIN ${FLUTTER_PLATFORM_PLUGIN_LIST}) |
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${PLUGIN}/aurora plugins/${PLUGIN}) |
||||
target_link_libraries(${BINARY_NAME} PRIVATE ${PLUGIN}_platform_plugin) |
||||
endforeach(PLUGIN) |
||||
|
||||
foreach(FFI_PLUGIN ${FLUTTER_FFI_PLUGIN_LIST}) |
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${FFI_PLUGIN}/aurora plugins/${FFI_PLUGIN}) |
||||
endforeach(FFI_PLUGIN) |
After Width: | Height: | Size: 9.7 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 6.5 KiB |
@ -0,0 +1,10 @@
|
||||
#include <flutter/application.h> |
||||
#include "generated_plugin_registrant.h" |
||||
|
||||
int main(int argc, char *argv[]) { |
||||
Application::Initialize(argc, argv); |
||||
Application::SetPixelRatio(1.8); |
||||
RegisterPlugins(); |
||||
Application::Launch(); |
||||
return 0; |
||||
} |
@ -0,0 +1,31 @@
|
||||
%global __provides_exclude_from ^%{_datadir}/%{name}/lib/.*$ |
||||
%global __requires_exclude ^lib(dconf|flutter-embedder|maliit-glib|appmanifest-.+|.+_platform_plugin)\\.so.*$ |
||||
|
||||
Name: com.example.shared_preferences_aurora_example |
||||
Summary: Demonstrates how to use the shared_preferences_aurora plugin. |
||||
Version: 0.1.0 |
||||
Release: 1 |
||||
License: Proprietary |
||||
Source0: %{name}-%{version}.tar.zst |
||||
|
||||
BuildRequires: cmake |
||||
BuildRequires: pkgconfig(flutter-embedder) |
||||
|
||||
%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 |
@ -0,0 +1,197 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'dart:async'; |
||||
|
||||
import 'package:flutter/services.dart'; |
||||
import 'package:shared_preferences/shared_preferences.dart'; |
||||
|
||||
void main() { |
||||
runApp(const MyApp()); |
||||
} |
||||
|
||||
class MyApp extends StatefulWidget { |
||||
const MyApp({super.key}); |
||||
|
||||
@override |
||||
State<MyApp> createState() => _MyAppState(); |
||||
} |
||||
|
||||
class _MyAppState extends State<MyApp> { |
||||
int? _counter; |
||||
bool? _repeat; |
||||
double? _decimal; |
||||
String? _action; |
||||
List<String>? _items; |
||||
String? _error; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
initPlatformState(); |
||||
} |
||||
|
||||
Future<void> initPlatformState() async { |
||||
try { |
||||
final SharedPreferences prefs = await SharedPreferences.getInstance(); |
||||
|
||||
// Save an integer value to 'counter' key. |
||||
await prefs.setInt('counter', 10); |
||||
// Save an boolean value to 'repeat' key. |
||||
await prefs.setBool('repeat', true); |
||||
// Save an double value to 'decimal' key. |
||||
await prefs.setDouble('decimal', 1.5); |
||||
// Save an String value to 'action' key. |
||||
await prefs.setString('action', 'Start'); |
||||
// Save an list of strings to 'items' key. |
||||
await prefs.setStringList('items', <String>['Earth', 'Moon', 'Sun']); |
||||
|
||||
// Try reading data from the 'counter' key. If it doesn't exist, returns null. |
||||
final int? counter = prefs.getInt('counter'); |
||||
// Try reading data from the 'repeat' key. If it doesn't exist, returns null. |
||||
final bool? repeat = prefs.getBool('repeat'); |
||||
// Try reading data from the 'decimal' key. If it doesn't exist, returns null. |
||||
final double? decimal = prefs.getDouble('decimal'); |
||||
// Try reading data from the 'action' key. If it doesn't exist, returns null. |
||||
final String? action = prefs.getString('action'); |
||||
// Try reading data from the 'items' key. If it doesn't exist, returns null. |
||||
final List<String>? items = prefs.getStringList('items'); |
||||
|
||||
setState(() { |
||||
_counter = counter; |
||||
_repeat = repeat; |
||||
_decimal = decimal; |
||||
_action = action; |
||||
_items = items; |
||||
}); |
||||
} on PlatformException { |
||||
setState(() { |
||||
_error = 'Platform exception'; |
||||
}); |
||||
} |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
const textStyleWhite = TextStyle(fontSize: 18, color: Colors.white); |
||||
const textStyleTitle = TextStyle(fontSize: 20, color: Colors.black); |
||||
const textStylePath = TextStyle(fontSize: 18, color: Colors.black54); |
||||
|
||||
const spaceMedium = SizedBox(height: 20); |
||||
const spaceSmall = SizedBox(height: 10); |
||||
|
||||
return MaterialApp( |
||||
home: Scaffold( |
||||
appBar: AppBar( |
||||
title: const Text('Example shared_preferences'), |
||||
), |
||||
body: Stack( |
||||
children: [ |
||||
// Error message |
||||
Visibility( |
||||
visible: _error != null, |
||||
child: Center( |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(16), |
||||
child: Container( |
||||
padding: const EdgeInsets.all(20), |
||||
decoration: const BoxDecoration( |
||||
color: Colors.redAccent, |
||||
borderRadius: BorderRadius.all(Radius.circular(10.0)), |
||||
), |
||||
child: Text( |
||||
_error ?? '', |
||||
style: textStyleWhite, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
), |
||||
// List directories path |
||||
Visibility( |
||||
visible: _error == null, |
||||
child: SingleChildScrollView( |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(16), |
||||
child: Center( |
||||
child: Column( |
||||
children: [ |
||||
// Info |
||||
Container( |
||||
padding: const EdgeInsets.all(20), |
||||
decoration: const BoxDecoration( |
||||
color: Colors.green, |
||||
borderRadius: |
||||
BorderRadius.all(Radius.circular(10.0)), |
||||
), |
||||
child: const Text( |
||||
'Demo application demonstration implementation of shared_preferences', |
||||
style: textStyleWhite, |
||||
textAlign: TextAlign.center, |
||||
), |
||||
), |
||||
const SizedBox(height: 30), |
||||
|
||||
const Text( |
||||
'Counter / int', |
||||
style: textStyleTitle, |
||||
), |
||||
spaceSmall, |
||||
Text( |
||||
_counter.toString(), |
||||
style: textStylePath, |
||||
), |
||||
|
||||
spaceMedium, |
||||
const Text( |
||||
'Repeat / bool', |
||||
style: textStyleTitle, |
||||
), |
||||
spaceSmall, |
||||
Text( |
||||
_repeat.toString(), |
||||
style: textStylePath, |
||||
), |
||||
|
||||
spaceMedium, |
||||
const Text( |
||||
'Decimal / double', |
||||
style: textStyleTitle, |
||||
), |
||||
spaceSmall, |
||||
Text( |
||||
_decimal.toString(), |
||||
style: textStylePath, |
||||
), |
||||
|
||||
spaceMedium, |
||||
const Text( |
||||
'Action / String', |
||||
style: textStyleTitle, |
||||
), |
||||
spaceSmall, |
||||
Text( |
||||
_action.toString(), |
||||
style: textStylePath, |
||||
), |
||||
|
||||
spaceMedium, |
||||
const Text( |
||||
'Items / String List', |
||||
style: textStyleTitle, |
||||
), |
||||
spaceSmall, |
||||
Text( |
||||
_items.toString(), |
||||
style: textStylePath, |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,299 @@
|
||||
# Generated by pub |
||||
# See https://dart.dev/tools/pub/glossary#lockfile |
||||
packages: |
||||
async: |
||||
dependency: transitive |
||||
description: |
||||
name: async |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.9.0" |
||||
boolean_selector: |
||||
dependency: transitive |
||||
description: |
||||
name: boolean_selector |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.0" |
||||
characters: |
||||
dependency: transitive |
||||
description: |
||||
name: characters |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.2.1" |
||||
clock: |
||||
dependency: transitive |
||||
description: |
||||
name: clock |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.1.1" |
||||
collection: |
||||
dependency: transitive |
||||
description: |
||||
name: collection |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.16.0" |
||||
cupertino_icons: |
||||
dependency: "direct main" |
||||
description: |
||||
name: cupertino_icons |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.0.5" |
||||
fake_async: |
||||
dependency: transitive |
||||
description: |
||||
name: fake_async |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.3.1" |
||||
ffi: |
||||
dependency: transitive |
||||
description: |
||||
name: ffi |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.0.2" |
||||
file: |
||||
dependency: transitive |
||||
description: |
||||
name: file |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "6.1.4" |
||||
flutter: |
||||
dependency: "direct main" |
||||
description: flutter |
||||
source: sdk |
||||
version: "0.0.0" |
||||
flutter_lints: |
||||
dependency: "direct dev" |
||||
description: |
||||
name: flutter_lints |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.0.1" |
||||
flutter_test: |
||||
dependency: "direct dev" |
||||
description: flutter |
||||
source: sdk |
||||
version: "0.0.0" |
||||
flutter_web_plugins: |
||||
dependency: transitive |
||||
description: flutter |
||||
source: sdk |
||||
version: "0.0.0" |
||||
js: |
||||
dependency: transitive |
||||
description: |
||||
name: js |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.6.4" |
||||
lints: |
||||
dependency: transitive |
||||
description: |
||||
name: lints |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.0.1" |
||||
matcher: |
||||
dependency: transitive |
||||
description: |
||||
name: matcher |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.12.12" |
||||
material_color_utilities: |
||||
dependency: transitive |
||||
description: |
||||
name: material_color_utilities |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.1.5" |
||||
meta: |
||||
dependency: transitive |
||||
description: |
||||
name: meta |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.8.0" |
||||
path: |
||||
dependency: transitive |
||||
description: |
||||
name: path |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.8.2" |
||||
path_provider_linux: |
||||
dependency: transitive |
||||
description: |
||||
name: path_provider_linux |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.10" |
||||
path_provider_platform_interface: |
||||
dependency: transitive |
||||
description: |
||||
name: path_provider_platform_interface |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.0.6" |
||||
path_provider_windows: |
||||
dependency: transitive |
||||
description: |
||||
name: path_provider_windows |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.6" |
||||
platform: |
||||
dependency: transitive |
||||
description: |
||||
name: platform |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "3.1.0" |
||||
plugin_platform_interface: |
||||
dependency: transitive |
||||
description: |
||||
name: plugin_platform_interface |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.4" |
||||
process: |
||||
dependency: transitive |
||||
description: |
||||
name: process |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "4.2.4" |
||||
shared_preferences: |
||||
dependency: "direct main" |
||||
description: |
||||
name: shared_preferences |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.1" |
||||
shared_preferences_android: |
||||
dependency: transitive |
||||
description: |
||||
name: shared_preferences_android |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.4" |
||||
shared_preferences_aurora: |
||||
dependency: "direct main" |
||||
description: |
||||
path: ".." |
||||
relative: true |
||||
source: path |
||||
version: "0.0.1" |
||||
shared_preferences_foundation: |
||||
dependency: transitive |
||||
description: |
||||
name: shared_preferences_foundation |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.2.2" |
||||
shared_preferences_linux: |
||||
dependency: transitive |
||||
description: |
||||
name: shared_preferences_linux |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.2.0" |
||||
shared_preferences_platform_interface: |
||||
dependency: transitive |
||||
description: |
||||
name: shared_preferences_platform_interface |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.2.0" |
||||
shared_preferences_web: |
||||
dependency: transitive |
||||
description: |
||||
name: shared_preferences_web |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.0" |
||||
shared_preferences_windows: |
||||
dependency: transitive |
||||
description: |
||||
name: shared_preferences_windows |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.2.0" |
||||
sky_engine: |
||||
dependency: transitive |
||||
description: flutter |
||||
source: sdk |
||||
version: "0.0.99" |
||||
source_span: |
||||
dependency: transitive |
||||
description: |
||||
name: source_span |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.9.0" |
||||
stack_trace: |
||||
dependency: transitive |
||||
description: |
||||
name: stack_trace |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.10.0" |
||||
stream_channel: |
||||
dependency: transitive |
||||
description: |
||||
name: stream_channel |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.0" |
||||
string_scanner: |
||||
dependency: transitive |
||||
description: |
||||
name: string_scanner |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.1.1" |
||||
term_glyph: |
||||
dependency: transitive |
||||
description: |
||||
name: term_glyph |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.2.1" |
||||
test_api: |
||||
dependency: transitive |
||||
description: |
||||
name: test_api |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.4.12" |
||||
vector_math: |
||||
dependency: transitive |
||||
description: |
||||
name: vector_math |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.2" |
||||
win32: |
||||
dependency: transitive |
||||
description: |
||||
name: win32 |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "4.1.4" |
||||
xdg_directories: |
||||
dependency: transitive |
||||
description: |
||||
name: xdg_directories |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.0.0" |
||||
sdks: |
||||
dart: ">=2.18.6 <3.0.0" |
||||
flutter: ">=3.0.0" |
@ -0,0 +1,84 @@
|
||||
name: shared_preferences_aurora_example |
||||
description: Demonstrates how to use the shared_preferences_aurora plugin. |
||||
|
||||
# The following line prevents the package from being accidentally published to |
||||
# pub.dev using `flutter pub publish`. This is preferred for private packages. |
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev |
||||
|
||||
environment: |
||||
sdk: '>=2.18.6 <3.0.0' |
||||
|
||||
# Dependencies specify other packages that your package needs in order to work. |
||||
# To automatically upgrade your package dependencies to the latest versions |
||||
# consider running `flutter pub upgrade --major-versions`. Alternatively, |
||||
# dependencies can be manually updated by changing the version numbers below to |
||||
# the latest version available on pub.dev. To see which dependencies have newer |
||||
# versions available, run `flutter pub outdated`. |
||||
dependencies: |
||||
flutter: |
||||
sdk: flutter |
||||
shared_preferences: ^2.1.1 |
||||
shared_preferences_aurora: |
||||
# When depending on this package from a real application you should use: |
||||
# shared_preferences_aurora: ^x.y.z |
||||
# See https://dart.dev/tools/pub/dependencies#version-constraints |
||||
# The example app is bundled with the plugin so we use a path dependency on |
||||
# the parent directory to use the current plugin's version. |
||||
path: ../ |
||||
|
||||
# The following adds the Cupertino Icons font to your application. |
||||
# Use with the CupertinoIcons class for iOS style icons. |
||||
cupertino_icons: ^1.0.2 |
||||
|
||||
dev_dependencies: |
||||
flutter_test: |
||||
sdk: flutter |
||||
|
||||
# The "flutter_lints" package below contains a set of recommended lints to |
||||
# encourage good coding practices. The lint set provided by the package is |
||||
# activated in the `analysis_options.yaml` file located at the root of your |
||||
# package. See that file for information about deactivating specific lint |
||||
# rules and activating additional ones. |
||||
flutter_lints: ^2.0.0 |
||||
|
||||
# For information on the generic Dart part of this file, see the |
||||
# following page: https://dart.dev/tools/pub/pubspec |
||||
|
||||
# The following section is specific to Flutter packages. |
||||
flutter: |
||||
|
||||
# The following line ensures that the Material Icons font is |
||||
# included with your application, so that you can use the icons in |
||||
# the material Icons class. |
||||
uses-material-design: true |
||||
|
||||
# To add assets to your application, add an assets section, like this: |
||||
# assets: |
||||
# - images/a_dot_burr.jpeg |
||||
# - images/a_dot_ham.jpeg |
||||
|
||||
# An image asset can refer to one or more resolution-specific "variants", see |
||||
# https://flutter.dev/assets-and-images/#resolution-aware |
||||
|
||||
# For details regarding adding assets from package dependencies, see |
||||
# https://flutter.dev/assets-and-images/#from-packages |
||||
|
||||
# To add custom fonts to your application, add a fonts section here, |
||||
# in this "flutter" section. Each entry in this list should have a |
||||
# "family" key with the font family name, and a "fonts" key with a |
||||
# list giving the asset and other descriptors for the font. For |
||||
# example: |
||||
# fonts: |
||||
# - family: Schyler |
||||
# fonts: |
||||
# - asset: fonts/Schyler-Regular.ttf |
||||
# - asset: fonts/Schyler-Italic.ttf |
||||
# style: italic |
||||
# - family: Trajan Pro |
||||
# fonts: |
||||
# - asset: fonts/TrajanPro.ttf |
||||
# - asset: fonts/TrajanPro_Bold.ttf |
||||
# weight: 700 |
||||
# |
||||
# For details regarding fonts from package dependencies, |
||||
# see https://flutter.dev/custom-fonts/#from-packages |
@ -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:shared_preferences_aurora_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, |
||||
); |
||||
}); |
||||
} |
@ -0,0 +1,64 @@
|
||||
import 'shared_preferences_aurora_platform_interface.dart'; |
||||
import 'package:flutter/foundation.dart'; |
||||
import 'package:flutter/services.dart'; |
||||
import 'package:shared_preferences_platform_interface/shared_preferences_platform_interface.dart'; |
||||
|
||||
class SharedPreferencesAurora extends SharedPreferencesStorePlatform { |
||||
SharedPreferencesAurora({ |
||||
@visibleForTesting SharedPreferencesAuroraPlatform? api, |
||||
}) : _api = api ?? SharedPreferencesAuroraPlatform.instance; |
||||
|
||||
late final SharedPreferencesAuroraPlatform _api; |
||||
|
||||
/// Registers this class as the default instance of [SharedPreferencesStorePlatform]. |
||||
static void registerWith() { |
||||
SharedPreferencesStorePlatform.instance = SharedPreferencesAurora(); |
||||
} |
||||
|
||||
static const String _defaultPrefix = 'flutter.'; |
||||
|
||||
@override |
||||
Future<bool> remove(String key) async { |
||||
return _api.remove(key); |
||||
} |
||||
|
||||
@override |
||||
Future<bool> setValue(String valueType, String key, Object value) async { |
||||
switch (valueType) { |
||||
case 'String': |
||||
return _api.setString(key, value as String); |
||||
case 'Bool': |
||||
return _api.setBool(key, value as bool); |
||||
case 'Int': |
||||
return _api.setInt(key, value as int); |
||||
case 'Double': |
||||
return _api.setDouble(key, value as double); |
||||
case 'StringList': |
||||
return _api.setStringList(key, value as List<String>); |
||||
} |
||||
throw PlatformException( |
||||
code: 'InvalidOperation', |
||||
message: '"$valueType" is not a supported type.'); |
||||
} |
||||
|
||||
@override |
||||
Future<bool> clear() { |
||||
return clearWithPrefix(_defaultPrefix); |
||||
} |
||||
|
||||
@override |
||||
Future<bool> clearWithPrefix(String prefix) async { |
||||
return _api.clearWithPrefix(prefix); |
||||
} |
||||
|
||||
@override |
||||
Future<Map<String, Object>> getAll() { |
||||
return getAllWithPrefix(_defaultPrefix); |
||||
} |
||||
|
||||
@override |
||||
Future<Map<String, Object>> getAllWithPrefix(String prefix) async { |
||||
final Map<Object?, Object?> data = await _api.getAllWithPrefix(prefix); |
||||
return data.cast<String, Object>(); |
||||
} |
||||
} |
@ -0,0 +1,82 @@
|
||||
import 'package:flutter/foundation.dart'; |
||||
import 'package:flutter/services.dart'; |
||||
|
||||
import 'shared_preferences_aurora_platform_interface.dart'; |
||||
|
||||
/// An implementation of [SharedPreferencesAuroraPlatform] that uses method channels. |
||||
class MethodChannelSharedPreferencesAurora |
||||
extends SharedPreferencesAuroraPlatform { |
||||
/// The method channel used to interact with the native platform. |
||||
@visibleForTesting |
||||
final methodChannel = const MethodChannel('shared_preferences_aurora'); |
||||
|
||||
@override |
||||
Future<bool> setInt(String key, int value) async { |
||||
return await methodChannel.invokeMethod<bool?>('setInt', { |
||||
'key': key, |
||||
'value': value, |
||||
}) ?? |
||||
false; |
||||
} |
||||
|
||||
@override |
||||
Future<bool> setBool(String key, bool value) async { |
||||
return await methodChannel.invokeMethod<bool?>('setBool', { |
||||
'key': key, |
||||
'value': value, |
||||
}) ?? |
||||
false; |
||||
} |
||||
|
||||
@override |
||||
Future<bool> setDouble(String key, double value) async { |
||||
return await methodChannel.invokeMethod<bool?>('setDouble', { |
||||
'key': key, |
||||
'value': value, |
||||
}) ?? |
||||
false; |
||||
} |
||||
|
||||
@override |
||||
Future<bool> setString(String key, String value) async { |
||||
return await methodChannel.invokeMethod<bool?>('setString', { |
||||
'key': key, |
||||
'value': value, |
||||
}) ?? |
||||
false; |
||||
} |
||||
|
||||
@override |
||||
Future<bool> setStringList(String key, List<String> value) async { |
||||
return await methodChannel.invokeMethod<bool?>('setStringList', { |
||||
'key': key, |
||||
'value': value, |
||||
}) ?? |
||||
false; |
||||
} |
||||
|
||||
@override |
||||
Future<bool> clearWithPrefix(String prefix) async { |
||||
return await methodChannel.invokeMethod<bool?>('clearWithPrefix', { |
||||
'prefix': prefix, |
||||
}) ?? |
||||
false; |
||||
} |
||||
|
||||
@override |
||||
Future<bool> remove(String key) async { |
||||
return await methodChannel.invokeMethod<bool?>('remove', { |
||||
'key': key, |
||||
}) ?? |
||||
false; |
||||
} |
||||
|
||||
@override |
||||
Future<Map<Object?, Object?>> getAllWithPrefix(String prefix) async { |
||||
return await methodChannel |
||||
.invokeMethod<Map<Object?, Object?>?>('getAllWithPrefix', { |
||||
'prefix': prefix, |
||||
}) ?? |
||||
{}; |
||||
} |
||||
} |
@ -0,0 +1,58 @@
|
||||
import 'package:plugin_platform_interface/plugin_platform_interface.dart'; |
||||
|
||||
import 'shared_preferences_aurora_method_channel.dart'; |
||||
|
||||
abstract class SharedPreferencesAuroraPlatform extends PlatformInterface { |
||||
/// Constructs a SharedPreferencesAuroraPlatform. |
||||
SharedPreferencesAuroraPlatform() : super(token: _token); |
||||
|
||||
static final Object _token = Object(); |
||||
|
||||
static SharedPreferencesAuroraPlatform _instance = |
||||
MethodChannelSharedPreferencesAurora(); |
||||
|
||||
/// The default instance of [SharedPreferencesAuroraPlatform] to use. |
||||
/// |
||||
/// Defaults to [MethodChannelSharedPreferencesAurora]. |
||||
static SharedPreferencesAuroraPlatform get instance => _instance; |
||||
|
||||
/// Platform-specific implementations should set this with their own |
||||
/// platform-specific class that extends [SharedPreferencesAuroraPlatform] when |
||||
/// they register themselves. |
||||
static set instance(SharedPreferencesAuroraPlatform instance) { |
||||
PlatformInterface.verifyToken(instance, _token); |
||||
_instance = instance; |
||||
} |
||||
|
||||
Future<bool> setInt(String key, int value) { |
||||
throw UnimplementedError('setInt() has not been implemented.'); |
||||
} |
||||
|
||||
Future<bool> setBool(String key, bool value) { |
||||
throw UnimplementedError('setBool() has not been implemented.'); |
||||
} |
||||
|
||||
Future<bool> setDouble(String key, double value) { |
||||
throw UnimplementedError('setDouble() has not been implemented.'); |
||||
} |
||||
|
||||
Future<bool> setString(String key, String value) { |
||||
throw UnimplementedError('setString() has not been implemented.'); |
||||
} |
||||
|
||||
Future<bool> setStringList(String key, List<String> value) { |
||||
throw UnimplementedError('setStringList() has not been implemented.'); |
||||
} |
||||
|
||||
Future<bool> clearWithPrefix(String prefix) { |
||||
throw UnimplementedError('onClearWithPrefix() has not been implemented.'); |
||||
} |
||||
|
||||
Future<bool> remove(String key) { |
||||
throw UnimplementedError('remove() has not been implemented.'); |
||||
} |
||||
|
||||
Future<Map<Object?, Object?>> getAllWithPrefix(String prefix) { |
||||
throw UnimplementedError('getAllWithPrefix() has not been implemented.'); |
||||
} |
||||
} |
@ -0,0 +1,26 @@
|
||||
name: shared_preferences_aurora |
||||
description: The Aurora OS implementation of shared_preferences. |
||||
version: 0.0.1 |
||||
homepage: |
||||
|
||||
environment: |
||||
sdk: '>=2.18.6 <3.0.0' |
||||
flutter: ">=2.5.0" |
||||
|
||||
dependencies: |
||||
flutter: |
||||
sdk: flutter |
||||
plugin_platform_interface: ^2.0.2 |
||||
shared_preferences_platform_interface: ^2.2.0 |
||||
|
||||
dev_dependencies: |
||||
flutter_test: |
||||
sdk: flutter |
||||
flutter_lints: ^2.0.0 |
||||
|
||||
flutter: |
||||
plugin: |
||||
platforms: |
||||
aurora: |
||||
pluginClass: SharedPreferencesAuroraPlugin |
||||
dartPluginClass: SharedPreferencesAurora |
@ -0,0 +1,71 @@
|
||||
import 'package:flutter/services.dart'; |
||||
import 'package:flutter_test/flutter_test.dart'; |
||||
import 'package:shared_preferences_aurora/shared_preferences_aurora_method_channel.dart'; |
||||
|
||||
void main() { |
||||
MethodChannelSharedPreferencesAurora platform = |
||||
MethodChannelSharedPreferencesAurora(); |
||||
const MethodChannel channel = MethodChannel('shared_preferences_aurora'); |
||||
|
||||
TestWidgetsFlutterBinding.ensureInitialized(); |
||||
|
||||
setUp(() { |
||||
channel.setMockMethodCallHandler((MethodCall methodCall) async { |
||||
switch (methodCall.method) { |
||||
case 'setInt': |
||||
return true; |
||||
case 'setBool': |
||||
return true; |
||||
case 'setDouble': |
||||
return true; |
||||
case 'setString': |
||||
return true; |
||||
case 'setStringList': |
||||
return true; |
||||
case 'clearWithPrefix': |
||||
return true; |
||||
case 'remove': |
||||
return true; |
||||
case 'getAllWithPrefix': |
||||
return <Object?, Object?>{}; |
||||
} |
||||
return null; |
||||
}); |
||||
}); |
||||
|
||||
tearDown(() { |
||||
channel.setMockMethodCallHandler(null); |
||||
}); |
||||
|
||||
test('onSetInt', () async { |
||||
expect(await platform.setInt('key', 42), true); |
||||
}); |
||||
|
||||
test('onSetBool', () async { |
||||
expect(await platform.setBool('key', true), true); |
||||
}); |
||||
|
||||
test('onSetDouble', () async { |
||||
expect(await platform.setDouble('key', 0.0), true); |
||||
}); |
||||
|
||||
test('onSetString', () async { |
||||
expect(await platform.setString('key', "Start"), true); |
||||
}); |
||||
|
||||
test('onSetStringList', () async { |
||||
expect(await platform.setStringList('key', <String>[]), true); |
||||
}); |
||||
|
||||
test('onClearWithPrefix', () async { |
||||
expect(await platform.clearWithPrefix('prefix'), true); |
||||
}); |
||||
|
||||
test('onRemove', () async { |
||||
expect(await platform.remove('key'), true); |
||||
}); |
||||
|
||||
test('onGetAllWithPrefix', () async { |
||||
expect(await platform.getAllWithPrefix('prefix'), <Object?, Object?>{}); |
||||
}); |
||||
} |
@ -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/ |
@ -0,0 +1,26 @@
|
||||
# sqflite_aurora |
||||
|
||||
The Aurora OS implementation of [`sqflite`](https://pub.dev/packages/sqflite). |
||||
|
||||
## Usage |
||||
|
||||
This package is not an endorsed implementation of `sqflite`. |
||||
Therefore, you have to include `sqflite_aurora` alongside `sqflite` as dependencies in your `pubspec.yaml` file. |
||||
|
||||
```yaml |
||||
dependencies: |
||||
sqflite: ^2.2.6 |
||||
sqflite_aurora: |
||||
git: git@os-git.omprussia.ru:non-oss/flutter/flutter-plugins.git |
||||
path: packages/sqflite/sqflite_aurora |
||||
``` |
||||
|
||||
Then you can import and use `sqflite` in your Dart code: |
||||
|
||||
```dart |
||||
import 'package:sqflite/sqflite.dart'; |
||||
``` |
||||
|
||||
### Preview example |
||||
|
||||
 |
@ -0,0 +1,118 @@
|
||||
# .clang-format for Qt Creator |
||||
# |
||||
# This is for clang-format >= 5.0. |
||||
# |
||||
# The configuration below follows the Qt Creator Coding Rules [1] as closely as |
||||
# possible. For documentation of the options, see [2]. |
||||
# |
||||
# Use ../../tests/manual/clang-format-for-qtc/test.cpp for documenting problems |
||||
# or testing changes. |
||||
# |
||||
# In case you update this configuration please also update the qtcStyle() in src\plugins\clangformat\clangformatutils.cpp |
||||
# |
||||
# [1] https://doc-snapshots.qt.io/qtcreator-extending/coding-style.html |
||||
# [2] https://clang.llvm.org/docs/ClangFormatStyleOptions.html |
||||
# |
||||
--- |
||||
Language: Cpp |
||||
AccessModifierOffset: -4 |
||||
AlignAfterOpenBracket: Align |
||||
AlignConsecutiveAssignments: false |
||||
AlignConsecutiveDeclarations: false |
||||
AlignConsecutiveMacros: true |
||||
AlignEscapedNewlines: DontAlign |
||||
AlignOperands: true |
||||
AlignTrailingComments: true |
||||
AllowAllParametersOfDeclarationOnNextLine: true |
||||
AllowShortBlocksOnASingleLine: false |
||||
AllowShortCaseLabelsOnASingleLine: false |
||||
AllowShortFunctionsOnASingleLine: Inline |
||||
AllowShortIfStatementsOnASingleLine: false |
||||
AllowShortLoopsOnASingleLine: false |
||||
AlwaysBreakAfterReturnType: None |
||||
AlwaysBreakBeforeMultilineStrings: false |
||||
AlwaysBreakTemplateDeclarations: true |
||||
BinPackArguments: false |
||||
BinPackParameters: false |
||||
BraceWrapping: |
||||
AfterClass: true |
||||
AfterControlStatement: false |
||||
AfterEnum: false |
||||
AfterFunction: true |
||||
AfterNamespace: false |
||||
AfterObjCDeclaration: false |
||||
AfterStruct: true |
||||
AfterUnion: false |
||||
BeforeCatch: false |
||||
BeforeElse: false |
||||
IndentBraces: false |
||||
SplitEmptyFunction: false |
||||
SplitEmptyRecord: false |
||||
SplitEmptyNamespace: false |
||||
BreakBeforeBinaryOperators: All |
||||
BreakBeforeBraces: Custom |
||||
BreakBeforeInheritanceComma: false |
||||
BreakBeforeTernaryOperators: true |
||||
BreakConstructorInitializersBeforeComma: false |
||||
BreakConstructorInitializers: BeforeComma |
||||
BreakAfterJavaFieldAnnotations: false |
||||
BreakStringLiterals: true |
||||
ColumnLimit: 100 |
||||
CommentPragmas: '^ IWYU pragma:' |
||||
CompactNamespaces: false |
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false |
||||
ConstructorInitializerIndentWidth: 4 |
||||
ContinuationIndentWidth: 4 |
||||
Cpp11BracedListStyle: true |
||||
DerivePointerAlignment: false |
||||
DisableFormat: false |
||||
ExperimentalAutoDetectBinPacking: false |
||||
FixNamespaceComments: true |
||||
ForEachMacros: |
||||
- forever # avoids { wrapped to next line |
||||
- foreach |
||||
- Q_FOREACH |
||||
- BOOST_FOREACH |
||||
IncludeCategories: |
||||
- Regex: '^<Q.*' |
||||
Priority: 200 |
||||
IncludeIsMainRegex: '(Test)?$' |
||||
IndentCaseLabels: false |
||||
IndentWidth: 4 |
||||
IndentWrappedFunctionNames: false |
||||
JavaScriptQuotes: Leave |
||||
JavaScriptWrapImports: true |
||||
KeepEmptyLinesAtTheStartOfBlocks: false |
||||
# Do not add QT_BEGIN_NAMESPACE/QT_END_NAMESPACE as this will indent lines in between. |
||||
MacroBlockBegin: "" |
||||
MacroBlockEnd: "" |
||||
MaxEmptyLinesToKeep: 1 |
||||
NamespaceIndentation: None |
||||
ObjCBlockIndentWidth: 4 |
||||
ObjCSpaceAfterProperty: false |
||||
ObjCSpaceBeforeProtocolList: true |
||||
PenaltyBreakAssignment: 150 |
||||
PenaltyBreakBeforeFirstCallParameter: 300 |
||||
PenaltyBreakComment: 500 |
||||
PenaltyBreakFirstLessLess: 400 |
||||
PenaltyBreakString: 600 |
||||
PenaltyExcessCharacter: 50 |
||||
PenaltyReturnTypeOnItsOwnLine: 300 |
||||
PointerAlignment: Right |
||||
ReflowComments: false |
||||
SortIncludes: true |
||||
SortUsingDeclarations: true |
||||
SpaceAfterCStyleCast: true |
||||
SpaceAfterTemplateKeyword: false |
||||
SpaceBeforeAssignmentOperators: true |
||||
SpaceBeforeParens: ControlStatements |
||||
SpaceInEmptyParentheses: false |
||||
SpacesBeforeTrailingComments: 1 |
||||
SpacesInAngles: false |
||||
SpacesInContainerLiterals: false |
||||
SpacesInCStyleCastParentheses: false |
||||
SpacesInParentheses: false |
||||
SpacesInSquareBrackets: false |
||||
Standard: Cpp11 |
||||
TabWidth: 4 |
||||
UseTab: Never |
@ -0,0 +1,28 @@
|
||||
cmake_minimum_required(VERSION 3.10) |
||||
|
||||
set(PROJECT_NAME sqflite_aurora) |
||||
set(PLUGIN_NAME sqflite_aurora_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") |
||||
|
||||
find_package(PkgConfig REQUIRED) |
||||
pkg_check_modules(FlutterEmbedder REQUIRED IMPORTED_TARGET flutter-embedder) |
||||
pkg_check_modules(SQLite REQUIRED IMPORTED_TARGET sqlite3) |
||||
|
||||
add_library(${PLUGIN_NAME} SHARED |
||||
lib/asynq.cpp |
||||
lib/database.cpp |
||||
lib/logger.cpp |
||||
lib/sqflite_aurora_plugin.cpp) |
||||
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) |
||||
target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::FlutterEmbedder PkgConfig::SQLite) |
||||
|
||||
target_include_directories(${PLUGIN_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) |
||||
target_compile_definitions(${PLUGIN_NAME} PRIVATE PLUGIN_IMPL) |
@ -0,0 +1,38 @@
|
||||
#ifndef FLUTTER_PLUGIN_SQFLITE_ASYNC_QUEUE_H |
||||
#define FLUTTER_PLUGIN_SQFLITE_ASYNC_QUEUE_H |
||||
|
||||
#include <condition_variable> |
||||
#include <functional> |
||||
#include <mutex> |
||||
#include <thread> |
||||
#include <queue> |
||||
|
||||
#ifdef PLUGIN_IMPL |
||||
#define PLUGIN_EXPORT __attribute__((visibility("default"))) |
||||
#else |
||||
#define PLUGIN_EXPORT |
||||
#endif |
||||
|
||||
class PLUGIN_EXPORT AsyncQueue final |
||||
{ |
||||
public: |
||||
typedef std::function<void()> Task; |
||||
|
||||
public: |
||||
AsyncQueue(); |
||||
~AsyncQueue(); |
||||
|
||||
void Push(const Task &task); |
||||
|
||||
private: |
||||
void run(); |
||||
|
||||
private: |
||||
bool m_running; |
||||
std::thread m_thread; |
||||
std::queue<Task> m_tasks; |
||||
std::mutex m_mutex; |
||||
std::condition_variable m_condition; |
||||
}; |
||||
|
||||
#endif /* FLUTTER_PLUGIN_SQFLITE_ASYNC_QUEUE_H */ |
@ -0,0 +1,57 @@
|
||||
#ifndef FLUTTER_PLUGIN_SQFLITE_CONSTANTS_H |
||||
#define FLUTTER_PLUGIN_SQFLITE_CONSTANTS_H |
||||
|
||||
#include <string> |
||||
|
||||
const std::string METHOD_GET_PLATFORM_VERSION = "getPlatformVersion"; |
||||
const std::string METHOD_GET_DATABASES_PATH = "getDatabasesPath"; |
||||
const std::string METHOD_DEBUG = "debug"; |
||||
const std::string METHOD_OPTIONS = "options"; |
||||
const std::string METHOD_OPEN_DATABASE = "openDatabase"; |
||||
const std::string METHOD_CLOSE_DATABASE = "closeDatabase"; |
||||
const std::string METHOD_INSERT = "insert"; |
||||
const std::string METHOD_EXECUTE = "execute"; |
||||
const std::string METHOD_QUERY = "query"; |
||||
const std::string METHOD_QUERY_CURSOR_NEXT = "queryCursorNext"; |
||||
const std::string METHOD_UPDATE = "update"; |
||||
const std::string METHOD_BATCH = "batch"; |
||||
const std::string METHOD_DELETE_DATABASE = "deleteDatabase"; |
||||
const std::string METHOD_DATABASE_EXISTS = "databaseExists"; |
||||
|
||||
const std::string ARG_ID = "id"; |
||||
const std::string ARG_PATH = "path"; |
||||
const std::string ARG_READ_ONLY = "readOnly"; |
||||
const std::string ARG_SINGLE_INSTANCE = "singleInstance"; |
||||
const std::string ARG_LOG_LEVEL = "logLevel"; |
||||
const std::string ARG_TRANSACTION_ID = "transactionId"; |
||||
const std::string ARG_IN_TRANSACTION = "inTransaction"; |
||||
const std::string ARG_RECOVERED = "recovered"; |
||||
const std::string ARG_RECOVERED_IN_TRANSACTION = "recoveredInTransaction"; |
||||
const std::string ARG_SQL = "sql"; |
||||
const std::string ARG_SQL_ARGUMENTS = "arguments"; |
||||
const std::string ARG_NO_RESULT = "noResult"; |
||||
const std::string ARG_CONTINUE_ON_ERROR = "continueOnError"; |
||||
const std::string ARG_COLUMNS = "columns"; |
||||
const std::string ARG_ROWS = "rows"; |
||||
const std::string ARG_DATABASES = "databases"; |
||||
const std::string ARG_COMMAND = "cmd"; |
||||
const std::string ARG_OPERATIONS = "operations"; |
||||
const std::string ARG_METHOD = "method"; |
||||
const std::string ARG_RESULT = "result"; |
||||
const std::string ARG_ERROR = "error"; |
||||
const std::string ARG_ERROR_CODE = "code"; |
||||
const std::string ARG_ERROR_MESSAGE = "message"; |
||||
const std::string ARG_ERROR_DATA = "data"; |
||||
const std::string ARG_CURSOR_PAGE_SIZE = "cursorPageSize"; |
||||
const std::string ARG_CURSOR_ID = "cursorId"; |
||||
const std::string ARG_CANCEL = "cancel"; |
||||
|
||||
const std::string ERROR_SQFLITE = "sqlite_error"; |
||||
const std::string ERROR_OPEN = "open_failed"; |
||||
const std::string ERROR_CLOSE = "close_failed"; |
||||
const std::string ERROR_CLOSED = "database_closed"; |
||||
const std::string ERROR_BAD_PARAM = "bad_param"; |
||||
const std::string ERROR_BAD_ARGS = "bad_arguments"; |
||||
const std::string ERROR_INTERNAL = "internal"; |
||||
|
||||
#endif /* FLUTTER_PLUGIN_SQFLITE_CONSTANTS_H */ |
@ -0,0 +1,111 @@
|
||||
#ifndef FLUTTER_PLUGIN_SQFLITE_DATABASE_H |
||||
#define FLUTTER_PLUGIN_SQFLITE_DATABASE_H |
||||
|
||||
#include <flutter/encodable.h> |
||||
#include <flutter/method-call.h> |
||||
|
||||
#include <sqflite_aurora/logger.h> |
||||
|
||||
#include <functional> |
||||
#include <optional> |
||||
#include <sqlite3.h> |
||||
#include <string> |
||||
#include <unordered_map> |
||||
#include <queue> |
||||
|
||||
#ifdef PLUGIN_IMPL |
||||
#define PLUGIN_EXPORT __attribute__((visibility("default"))) |
||||
#else |
||||
#define PLUGIN_EXPORT |
||||
#endif |
||||
|
||||
class PLUGIN_EXPORT Database final |
||||
{ |
||||
public: |
||||
enum TransactionID { |
||||
None = -2, |
||||
Force = -1, |
||||
}; |
||||
|
||||
struct Cursor |
||||
{ |
||||
int64_t id; |
||||
sqlite3_stmt *stmt; |
||||
int64_t pageSize; |
||||
}; |
||||
|
||||
struct Operation |
||||
{ |
||||
std::string method; |
||||
std::string sql; |
||||
Encodable::List arguments; |
||||
}; |
||||
|
||||
public: |
||||
Database(int id, const std::string &path, bool singleton, const Logger &logger); |
||||
~Database(); |
||||
|
||||
public: |
||||
std::optional<std::string> Open(); |
||||
std::optional<std::string> OpenReadOnly(); |
||||
std::optional<std::string> Close(); |
||||
std::optional<std::string> Execute(const std::string &sql, const Encodable::List &args); |
||||
std::optional<std::string> QueryCursorNext(int cursorID, bool cancel, Encodable::Map &result); |
||||
std::optional<std::string> Query(const std::string &sql, |
||||
const Encodable::List &args, |
||||
Encodable::Map &result); |
||||
std::optional<std::string> QueryWithPageSize(const std::string &sql, |
||||
const Encodable::List &args, |
||||
int64_t pageSize, |
||||
Encodable::Map &result); |
||||
std::optional<std::string> Insert(const std::string &sql, |
||||
const Encodable::List &args, |
||||
int &insertID); |
||||
std::optional<std::string> Update(const std::string &sql, |
||||
const Encodable::List &args, |
||||
int &updated); |
||||
std::optional<std::string> Batch(const std::vector<Operation> &operations, |
||||
bool continueOnError, |
||||
Encodable::List &results); |
||||
|
||||
void EnterInTransaction(); |
||||
void LeaveTransaction(); |
||||
int CurrentTransactionID(); |
||||
|
||||
typedef std::function<void()> SqlCommandCallback; |
||||
void ProcessSqlCommand(int transactionID, const SqlCommandCallback &callback); |
||||
|
||||
public: |
||||
bool IsOpen() const; |
||||
bool IsSingleInstance() const; |
||||
bool IsInTransaction() const; |
||||
bool IsInMemory() const; |
||||
bool IsReadOnly() const; |
||||
|
||||
const std::string &Path() const; |
||||
int64_t ID() const; |
||||
Logger::Level LogLevel() const; |
||||
|
||||
private: |
||||
std::string currentErrorMessage(); |
||||
std::optional<std::string> createParentDir(); |
||||
std::optional<std::string> bindStmtArgs(sqlite3_stmt *stmt, const Encodable::List &args); |
||||
|
||||
void closeCursor(const Cursor &cursor); |
||||
std::optional<std::string> resultFromCursor(const Cursor &cursor, Encodable::Map &result); |
||||
|
||||
private: |
||||
int64_t id; |
||||
std::string path; |
||||
bool isSingleInstance; |
||||
bool isReadOnly; |
||||
Logger logger; |
||||
int transactionID; |
||||
int currentTransactionID; |
||||
std::queue<SqlCommandCallback> pendingSqlCallbacks; |
||||
int64_t cursorID; |
||||
std::unordered_map<int64_t, Cursor> cursors; |
||||
sqlite3 *db; |
||||
}; |
||||
|
||||
#endif /* FLUTTER_PLUGIN_SQFLITE_DATABASE_H */ |
@ -0,0 +1,40 @@
|
||||
#ifndef FLUTTER_PLUGIN_SQFLITE_LOGGER_H |
||||
#define FLUTTER_PLUGIN_SQFLITE_LOGGER_H |
||||
|
||||
#include <flutter/logger.h> |
||||
#include <string> |
||||
|
||||
#ifdef PLUGIN_IMPL |
||||
#define PLUGIN_EXPORT __attribute__((visibility("default"))) |
||||
#else |
||||
#define PLUGIN_EXPORT |
||||
#endif |
||||
|
||||
class PLUGIN_EXPORT Logger final |
||||
{ |
||||
public: |
||||
enum Level { |
||||
None = 0, |
||||
Sql, |
||||
Verbose, |
||||
}; |
||||
|
||||
public: |
||||
Logger(Level level, const std::string &tag); |
||||
|
||||
Level LogLevel() const; |
||||
void SetLogLevel(Level level); |
||||
|
||||
std::string Tag() const; |
||||
void SetTag(const std::string &tag); |
||||
|
||||
std::ostream &verb(); |
||||
std::ostream &sql(); |
||||
|
||||
private: |
||||
Level level; |
||||
std::string tag; |
||||
std::ostream devnull; |
||||
}; |
||||
|
||||
#endif /* FLUTTER_PLUGIN_SQFLITE_LOGGER_H */ |
@ -0,0 +1,67 @@
|
||||
#ifndef FLUTTER_PLUGIN_SQFLITE_H |
||||
#define FLUTTER_PLUGIN_SQFLITE_H |
||||
|
||||
#include <flutter/plugin-interface.h> |
||||
|
||||
#include <sqflite_aurora/asynq.h> |
||||
#include <sqflite_aurora/database.h> |
||||
|
||||
#include <memory> |
||||
#include <mutex> |
||||
#include <unordered_map> |
||||
|
||||
#ifdef PLUGIN_IMPL |
||||
#define PLUGIN_EXPORT __attribute__((visibility("default"))) |
||||
#else |
||||
#define PLUGIN_EXPORT |
||||
#endif |
||||
|
||||
class PLUGIN_EXPORT SqfliteAuroraPlugin final : public PluginInterface |
||||
{ |
||||
public: |
||||
SqfliteAuroraPlugin(); |
||||
void RegisterWithRegistrar(PluginRegistrar ®istrar) override; |
||||
|
||||
private: |
||||
void onMethodCall(const MethodCall &call); |
||||
void onPlatformVersionCall(const MethodCall &call); |
||||
void onOpenDatabaseCall(const MethodCall &call); |
||||
void onCloseDatabaseCall(const MethodCall &call); |
||||
void onDeleteDatabaseCall(const MethodCall &call); |
||||
void onDatabaseExistsCall(const MethodCall &call); |
||||
void onGetDatabasesPathCall(const MethodCall &call); |
||||
void onOptionsCall(const MethodCall &call); |
||||
void onDebugCall(const MethodCall &call); |
||||
void onExecuteCall(const MethodCall &call); |
||||
void onQueryCall(const MethodCall &call); |
||||
void onQueryCursorNextCall(const MethodCall &call); |
||||
void onUpdateCall(const MethodCall &call); |
||||
void onInsertCall(const MethodCall &call); |
||||
void onBatchCall(const MethodCall &call); |
||||
|
||||
std::shared_ptr<Database> databaseByPath(const std::string &path); |
||||
std::shared_ptr<Database> databaseByID(int64_t id); |
||||
|
||||
void databaseRemove(std::shared_ptr<Database> db); |
||||
void databaseAdd(std::shared_ptr<Database> db); |
||||
|
||||
void success(const MethodCall &call, const Encodable &result = nullptr); |
||||
void error(const MethodCall &call, |
||||
const std::string &error, |
||||
const std::string &message, |
||||
const std::string &desc = "", |
||||
const Encodable &details = nullptr); |
||||
|
||||
Encodable::Map makeOpenResult(int64_t dbID, bool recovered, bool recoveredInTransaction); |
||||
|
||||
private: |
||||
std::mutex mutex; |
||||
std::unordered_map<std::string, std::shared_ptr<Database>> singletonDatabases; |
||||
std::unordered_map<int64_t, std::shared_ptr<Database>> databases; |
||||
int64_t dbID = 0; |
||||
Logger logger; |
||||
bool queryAsMapList = false; |
||||
AsyncQueue asynq; |
||||
}; |
||||
|
||||
#endif /* FLUTTER_PLUGIN_SQFLITE_H */ |
@ -0,0 +1,41 @@
|
||||
#include <sqflite_aurora/asynq.h> |
||||
|
||||
AsyncQueue::AsyncQueue() |
||||
: m_running(false) |
||||
, m_thread() |
||||
{} |
||||
|
||||
AsyncQueue::~AsyncQueue() |
||||
{ |
||||
m_running = false; |
||||
m_thread.join(); |
||||
} |
||||
|
||||
void AsyncQueue::Push(const Task &task) |
||||
{ |
||||
if (!m_running) { |
||||
m_running = true; |
||||
m_tasks.push(task); |
||||
m_thread = std::thread(&AsyncQueue::run, this); |
||||
return; |
||||
} |
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex); |
||||
|
||||
m_tasks.push(task); |
||||
m_condition.notify_one(); |
||||
} |
||||
|
||||
void AsyncQueue::run() |
||||
{ |
||||
while (m_running) { |
||||
std::unique_lock<std::mutex> lock(m_mutex); |
||||
m_condition.wait(lock, [this] { return !m_tasks.empty(); }); |
||||
|
||||
const auto task = m_tasks.front(); |
||||
m_tasks.pop(); |
||||
lock.unlock(); |
||||
|
||||
task(); |
||||
} |
||||
} |
@ -0,0 +1,631 @@
|
||||
#include <sqflite_aurora/constants.h> |
||||
#include <sqflite_aurora/database.h> |
||||
|
||||
#include <filesystem> |
||||
#include <limits> |
||||
|
||||
namespace { |
||||
|
||||
void addError(Encodable::List &results, const std::string &error) |
||||
{ |
||||
results.emplace_back(Encodable::Map{ |
||||
{"error", Encodable::Map{{"message", error}}}, |
||||
}); |
||||
} |
||||
|
||||
template<typename T> |
||||
void addResult(Encodable::List &results, const T &result) |
||||
{ |
||||
results.emplace_back(Encodable::Map{{"result", result}}); |
||||
} |
||||
|
||||
} /* namespace */ |
||||
|
||||
Database::Database(int id, const std::string &path, bool singleton, const Logger &logger) |
||||
: id(id) |
||||
, path(path) |
||||
, isSingleInstance(singleton) |
||||
, logger(logger.LogLevel(), logger.Tag() + "-db-" + std::to_string(id)) |
||||
, transactionID(0) |
||||
, currentTransactionID(TransactionID::None) |
||||
, cursorID(0) |
||||
, db(nullptr) |
||||
{} |
||||
|
||||
Database::~Database() |
||||
{ |
||||
Close(); |
||||
} |
||||
|
||||
std::optional<std::string> Database::Open() |
||||
{ |
||||
const auto error = this->createParentDir(); |
||||
if (error) |
||||
return error; |
||||
|
||||
int result_code = sqlite3_open_v2(this->path.c_str(), |
||||
&this->db, |
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, |
||||
nullptr); |
||||
if (result_code != SQLITE_OK) |
||||
return this->currentErrorMessage(); |
||||
|
||||
this->isReadOnly = false; |
||||
return std::nullopt; |
||||
} |
||||
|
||||
std::optional<std::string> Database::OpenReadOnly() |
||||
{ |
||||
const auto error = this->createParentDir(); |
||||
if (error) |
||||
return error; |
||||
|
||||
int result_code = sqlite3_open_v2(this->path.c_str(), &this->db, SQLITE_OPEN_READONLY, nullptr); |
||||
if (result_code != SQLITE_OK) |
||||
return this->currentErrorMessage(); |
||||
|
||||
this->isReadOnly = true; |
||||
return std::nullopt; |
||||
} |
||||
|
||||
std::optional<std::string> Database::Close() |
||||
{ |
||||
if (sqlite3_close_v2(this->db) != SQLITE_OK) |
||||
return this->currentErrorMessage(); |
||||
|
||||
this->db = nullptr; |
||||
this->pendingSqlCallbacks = {}; |
||||
|
||||
return std::nullopt; |
||||
} |
||||
|
||||
std::optional<std::string> Database::Execute(const std::string &sql, const Encodable::List &args) |
||||
{ |
||||
sqlite3_stmt *stmt = nullptr; |
||||
|
||||
if (sqlite3_prepare_v2(this->db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) |
||||
return this->currentErrorMessage(); |
||||
|
||||
const auto error = this->bindStmtArgs(stmt, args); |
||||
|
||||
if (error) { |
||||
sqlite3_finalize(stmt); |
||||
return error; |
||||
} |
||||
|
||||
while (true) { |
||||
int status = sqlite3_step(stmt); |
||||
|
||||
if (status == SQLITE_ROW) |
||||
continue; |
||||
|
||||
if (status == SQLITE_DONE) |
||||
break; |
||||
|
||||
sqlite3_finalize(stmt); |
||||
return this->currentErrorMessage(); |
||||
} |
||||
|
||||
sqlite3_finalize(stmt); |
||||
return std::nullopt; |
||||
} |
||||
|
||||
std::optional<std::string> Database::Query(const std::string &sql, |
||||
const Encodable::List &args, |
||||
Encodable::Map &result) |
||||
{ |
||||
sqlite3_stmt *stmt = nullptr; |
||||
|
||||
if (sqlite3_prepare_v2(this->db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) |
||||
return this->currentErrorMessage(); |
||||
|
||||
const auto error = this->bindStmtArgs(stmt, args); |
||||
|
||||
if (error) { |
||||
sqlite3_finalize(stmt); |
||||
return error; |
||||
} |
||||
|
||||
Encodable::List columns; |
||||
|
||||
for (int idx = 0; idx < sqlite3_column_count(stmt); idx++) |
||||
columns.emplace_back(sqlite3_column_name(stmt, idx)); |
||||
|
||||
Encodable::List rows; |
||||
|
||||
while (true) { |
||||
int status = sqlite3_step(stmt); |
||||
|
||||
if (status == SQLITE_ROW) { |
||||
Encodable::List row; |
||||
|
||||
for (size_t idx = 0; idx < columns.size(); idx++) { |
||||
switch (sqlite3_column_type(stmt, idx)) { |
||||
case SQLITE_INTEGER: |
||||
row.emplace_back(sqlite3_column_int64(stmt, idx)); |
||||
break; |
||||
case SQLITE_FLOAT: |
||||
row.emplace_back(sqlite3_column_double(stmt, idx)); |
||||
break; |
||||
case SQLITE_TEXT: |
||||
row.emplace_back(reinterpret_cast<const char *>(sqlite3_column_text(stmt, idx))); |
||||
break; |
||||
case SQLITE_BLOB: { |
||||
const uint8_t *blob = reinterpret_cast<const uint8_t *>( |
||||
sqlite3_column_blob(stmt, idx)); |
||||
std::vector<uint8_t> v(blob, blob + sqlite3_column_bytes(stmt, idx)); |
||||
row.emplace_back(v); |
||||
break; |
||||
} |
||||
case SQLITE_NULL: { |
||||
const char *columnDecltype = sqlite3_column_decltype(stmt, idx); |
||||
|
||||
if (columnDecltype != NULL && std::string("BLOB") == columnDecltype) |
||||
row.emplace_back(Encodable::Uint8List{}); |
||||
else |
||||
row.emplace_back(nullptr); |
||||
|
||||
break; |
||||
} |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
|
||||
rows.emplace_back(row); |
||||
continue; |
||||
} |
||||
|
||||
if (status == SQLITE_DONE) |
||||
break; |
||||
|
||||
sqlite3_finalize(stmt); |
||||
return this->currentErrorMessage(); |
||||
} |
||||
|
||||
result = Encodable::Map{{"columns", columns}, {"rows", rows}}; |
||||
|
||||
sqlite3_finalize(stmt); |
||||
return std::nullopt; |
||||
} |
||||
|
||||
std::optional<std::string> Database::QueryWithPageSize(const std::string &sql, |
||||
const Encodable::List &args, |
||||
int64_t pageSize, |
||||
Encodable::Map &result) |
||||
{ |
||||
sqlite3_stmt *stmt = nullptr; |
||||
|
||||
if (sqlite3_prepare_v2(this->db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) |
||||
return this->currentErrorMessage(); |
||||
|
||||
const auto error = this->bindStmtArgs(stmt, args); |
||||
|
||||
if (error) |
||||
return error; |
||||
|
||||
this->cursorID += 1; |
||||
this->cursors[cursorID] = Cursor{this->cursorID, stmt, pageSize}; |
||||
|
||||
return resultFromCursor(this->cursors[cursorID], result); |
||||
} |
||||
|
||||
std::optional<std::string> Database::QueryCursorNext(int cursorID, |
||||
bool cancel, |
||||
Encodable::Map &result) |
||||
{ |
||||
this->logger.verb() << "querying cursor next (ID=" << cursorID << "; CANCEL=" << cancel << ")" |
||||
<< std::endl; |
||||
|
||||
if (!this->cursors.count(cursorID)) |
||||
return "cursor not found"; |
||||
|
||||
const Cursor &cursor = this->cursors[cursorID]; |
||||
|
||||
if (cancel) { |
||||
this->closeCursor(cursor); |
||||
return std::nullopt; |
||||
} |
||||
|
||||
return this->resultFromCursor(cursor, result); |
||||
} |
||||
|
||||
std::optional<std::string> Database::Insert(const std::string &sql, |
||||
const Encodable::List &args, |
||||
int &insertID) |
||||
{ |
||||
if (this->isReadOnly) |
||||
return "database is readonly"; |
||||
|
||||
const auto error = this->Execute(sql, args); |
||||
|
||||
if (error) |
||||
return error; |
||||
|
||||
const int updated = sqlite3_changes(this->db); |
||||
|
||||
this->logger.sql() << "rows updated: " << updated << std::endl; |
||||
|
||||
if (updated == 0) { |
||||
insertID = 0; |
||||
return std::nullopt; |
||||
} |
||||
|
||||
insertID = sqlite3_last_insert_rowid(this->db); |
||||
this->logger.sql() << "last inserted row id: " << insertID << std::endl; |
||||
|
||||
return std::nullopt; |
||||
} |
||||
|
||||
std::optional<std::string> Database::Update(const std::string &sql, |
||||
const Encodable::List &args, |
||||
int &updated) |
||||
{ |
||||
if (this->isReadOnly) |
||||
return "database is readonly"; |
||||
|
||||
const auto error = this->Execute(sql, args); |
||||
|
||||
if (error) |
||||
return error; |
||||
|
||||
updated = sqlite3_changes(this->db); |
||||
this->logger.sql() << "rows updated: " << updated << std::endl; |
||||
|
||||
return std::nullopt; |
||||
} |
||||
|
||||
void Database::ProcessSqlCommand(int transactionID, const SqlCommandCallback &callback) |
||||
{ |
||||
if (this->currentTransactionID == TransactionID::None) { |
||||
callback(); |
||||
return; |
||||
} |
||||
|
||||
if (transactionID == this->currentTransactionID || transactionID == TransactionID::Force) { |
||||
callback(); |
||||
|
||||
if (this->currentTransactionID == TransactionID::None) { |
||||
while (!this->pendingSqlCallbacks.empty() && this->IsOpen()) { |
||||
const auto &pendingCallback = this->pendingSqlCallbacks.front(); |
||||
pendingCallback(); |
||||
this->pendingSqlCallbacks.pop(); |
||||
} |
||||
} |
||||
|
||||
return; |
||||
} |
||||
|
||||
this->pendingSqlCallbacks.push(callback); |
||||
} |
||||
|
||||
void Database::EnterInTransaction() |
||||
{ |
||||
this->transactionID += 1; |
||||
this->currentTransactionID = this->transactionID; |
||||
} |
||||
|
||||
void Database::LeaveTransaction() |
||||
{ |
||||
this->currentTransactionID = TransactionID::None; |
||||
} |
||||
|
||||
int Database::CurrentTransactionID() |
||||
{ |
||||
return this->currentTransactionID; |
||||
} |
||||
|
||||
bool Database::IsOpen() const |
||||
{ |
||||
return this->db != nullptr; |
||||
} |
||||
|
||||
const std::string &Database::Path() const |
||||
{ |
||||
return this->path; |
||||
} |
||||
|
||||
bool Database::IsSingleInstance() const |
||||
{ |
||||
return this->isSingleInstance; |
||||
} |
||||
|
||||
bool Database::IsReadOnly() const |
||||
{ |
||||
return this->isReadOnly; |
||||
} |
||||
|
||||
bool Database::IsInTransaction() const |
||||
{ |
||||
return this->currentTransactionID != TransactionID::None; |
||||
} |
||||
|
||||
int64_t Database::ID() const |
||||
{ |
||||
return this->id; |
||||
} |
||||
|
||||
Logger::Level Database::LogLevel() const |
||||
{ |
||||
return this->logger.LogLevel(); |
||||
} |
||||
|
||||
bool Database::IsInMemory() const |
||||
{ |
||||
return this->path.empty() || this->path == ":memory:"; |
||||
} |
||||
|
||||
std::string Database::currentErrorMessage() |
||||
{ |
||||
const auto message = sqlite3_errmsg(this->db); |
||||
const auto code = sqlite3_extended_errcode(this->db); |
||||
|
||||
return std::string(message) + " (" + std::to_string(code) + ")"; |
||||
} |
||||
|
||||
std::optional<std::string> Database::createParentDir() |
||||
{ |
||||
if (this->IsInMemory()) |
||||
return std::nullopt; |
||||
|
||||
const auto parentDir = std::filesystem::path(this->path).parent_path(); |
||||
|
||||
if (std::filesystem::exists(parentDir)) |
||||
return std::nullopt; |
||||
|
||||
if (std::filesystem::create_directories(parentDir)) |
||||
return std::nullopt; |
||||
|
||||
return "couldn't create parent directory"; |
||||
} |
||||
|
||||
std::optional<std::string> Database::bindStmtArgs(sqlite3_stmt *stmt, const Encodable::List &args) |
||||
{ |
||||
int result = SQLITE_OK; |
||||
|
||||
for (size_t i = 0; i < args.size(); i++) { |
||||
auto idx = i + 1; |
||||
auto &arg = args[i]; |
||||
|
||||
if (arg.IsNull()) { |
||||
result = sqlite3_bind_null(stmt, idx); |
||||
} else if (arg.IsBoolean()) { |
||||
result = sqlite3_bind_int(stmt, idx, static_cast<int>(arg.GetBoolean())); |
||||
} else if (arg.IsInt()) { |
||||
const int64_t value = arg.GetInt(); |
||||
|
||||
const int32_t i32min = std::numeric_limits<int32_t>::min(); |
||||
const int32_t i32max = std::numeric_limits<int32_t>::max(); |
||||
|
||||
if (value < i32min || value > i32max) |
||||
result = sqlite3_bind_int64(stmt, idx, arg.GetInt()); |
||||
else |
||||
result = sqlite3_bind_int64(stmt, idx, static_cast<int32_t>(arg.GetInt())); |
||||
} else if (arg.IsFloat()) { |
||||
result = sqlite3_bind_double(stmt, idx, arg.GetFloat()); |
||||
} else if (arg.IsString()) { |
||||
const auto &string = arg.GetString(); |
||||
result = sqlite3_bind_text(stmt, idx, string.c_str(), string.size(), SQLITE_TRANSIENT); |
||||
} else if (arg.IsUint8List()) { |
||||
const auto &container = arg.GetUint8List(); |
||||
result = sqlite3_bind_blob(stmt, |
||||
idx, |
||||
container.data(), |
||||
container.size(), |
||||
SQLITE_TRANSIENT); |
||||
} else if (arg.IsInt32List()) { |
||||
const auto &container = arg.GetInt32List(); |
||||
result = sqlite3_bind_blob(stmt, |
||||
idx, |
||||
container.data(), |
||||
container.size() * sizeof(int32_t), |
||||
SQLITE_TRANSIENT); |
||||
} else if (arg.IsInt64List()) { |
||||
const auto &container = arg.GetInt64List(); |
||||
result = sqlite3_bind_blob(stmt, |
||||
idx, |
||||
container.data(), |
||||
container.size() * sizeof(int64_t), |
||||
SQLITE_TRANSIENT); |
||||
} else if (arg.IsFloat32List()) { |
||||
const auto &container = arg.GetFloat32List(); |
||||
result = sqlite3_bind_blob(stmt, |
||||
idx, |
||||
container.data(), |
||||
container.size() * sizeof(float), |
||||
SQLITE_TRANSIENT); |
||||
} else if (arg.IsFloat64List()) { |
||||
const auto &container = arg.GetFloat64List(); |
||||
result = sqlite3_bind_blob(stmt, |
||||
idx, |
||||
container.data(), |
||||
container.size() * sizeof(double), |
||||
SQLITE_TRANSIENT); |
||||
} else if (arg.IsList()) { |
||||
/* only bytes list is supported */ |
||||
std::vector<uint8_t> container; |
||||
|
||||
for (const auto &entry : arg.GetList()) { |
||||
if (!entry.IsInt()) |
||||
return "only list of bytes is supported for statement parameter"; |
||||
|
||||
const auto value = entry.GetInt(); |
||||
|
||||
if (value < 0 || value > 255) |
||||
return "only list of bytes is supported for statement parameter"; |
||||
|
||||
container.push_back(static_cast<uint8_t>(value)); |
||||
} |
||||
|
||||
result = sqlite3_bind_blob(stmt, |
||||
idx, |
||||
container.data(), |
||||
container.size(), |
||||
SQLITE_TRANSIENT); |
||||
} else { |
||||
return "statement parameter has invalid type"; |
||||
} |
||||
|
||||
if (result != SQLITE_OK) |
||||
return this->currentErrorMessage(); |
||||
} |
||||
|
||||
this->logger.sql() << sqlite3_expanded_sql(stmt) << std::endl; |
||||
return std::nullopt; |
||||
} |
||||
|
||||
void Database::closeCursor(const Cursor &cursor) |
||||
{ |
||||
logger.verb() << "closing cursor (ID=" << cursor.id << ")" << std::endl; |
||||
sqlite3_finalize(cursor.stmt); |
||||
this->cursors.erase(cursor.id); |
||||
} |
||||
|
||||
std::optional<std::string> Database::resultFromCursor(const Cursor &cursor, Encodable::Map &result) |
||||
{ |
||||
Encodable::List columns; |
||||
|
||||
for (int idx = 0; idx < sqlite3_column_count(cursor.stmt); idx++) |
||||
columns.emplace_back(sqlite3_column_name(cursor.stmt, idx)); |
||||
|
||||
Encodable::List rows; |
||||
int status = SQLITE_ROW; |
||||
|
||||
while (static_cast<int64_t>(rows.size()) < cursor.pageSize) { |
||||
status = sqlite3_step(cursor.stmt); |
||||
|
||||
if (status == SQLITE_ROW) { |
||||
Encodable::List row; |
||||
|
||||
for (size_t idx = 0; idx < columns.size(); idx++) { |
||||
switch (sqlite3_column_type(cursor.stmt, idx)) { |
||||
case SQLITE_INTEGER: |
||||
row.emplace_back(sqlite3_column_int64(cursor.stmt, idx)); |
||||
break; |
||||
case SQLITE_FLOAT: |
||||
row.emplace_back(sqlite3_column_double(cursor.stmt, idx)); |
||||
break; |
||||
case SQLITE_TEXT: |
||||
row.emplace_back( |
||||
reinterpret_cast<const char *>(sqlite3_column_text(cursor.stmt, idx))); |
||||
break; |
||||
case SQLITE_BLOB: { |
||||
const uint8_t *blob = reinterpret_cast<const uint8_t *>( |
||||
sqlite3_column_blob(cursor.stmt, idx)); |
||||
std::vector<uint8_t> v(blob, blob + sqlite3_column_bytes(cursor.stmt, idx)); |
||||
row.emplace_back(v); |
||||
break; |
||||
} |
||||
case SQLITE_NULL: { |
||||
const char *columnDecltype = sqlite3_column_decltype(cursor.stmt, idx); |
||||
|
||||
if (columnDecltype != NULL && std::string("BLOB") == columnDecltype) |
||||
row.emplace_back(Encodable::Uint8List{}); |
||||
else |
||||
row.emplace_back(nullptr); |
||||
|
||||
break; |
||||
} |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
|
||||
rows.emplace_back(row); |
||||
continue; |
||||
} |
||||
|
||||
if (status == SQLITE_DONE) { |
||||
this->closeCursor(cursor); |
||||
break; |
||||
} |
||||
|
||||
this->closeCursor(cursor); |
||||
return this->currentErrorMessage(); |
||||
} |
||||
|
||||
result = Encodable::Map{{"columns", columns}, {"rows", rows}}; |
||||
|
||||
if (status != SQLITE_DONE) |
||||
result.insert({ARG_CURSOR_ID, cursor.id}); |
||||
|
||||
return std::nullopt; |
||||
} |
||||
|
||||
std::optional<std::string> Database::Batch(const std::vector<Operation> &operations, |
||||
bool continueOnError, |
||||
Encodable::List &results) |
||||
{ |
||||
for (const auto &operation : operations) { |
||||
const auto &method = operation.method; |
||||
|
||||
if (method == METHOD_INSERT) { |
||||
int insertID = 0; |
||||
const auto error = this->Insert(operation.sql, operation.arguments, insertID); |
||||
|
||||
if (error) { |
||||
if (!continueOnError) |
||||
return error; |
||||
|
||||
addError(results, *error); |
||||
continue; |
||||
} |
||||
|
||||
if (insertID == 0) |
||||
addResult(results, nullptr); |
||||
else |
||||
addResult(results, insertID); |
||||
|
||||
continue; |
||||
} |
||||
|
||||
if (method == METHOD_EXECUTE) { |
||||
const auto error = this->Execute(operation.sql, operation.arguments); |
||||
|
||||
if (error) { |
||||
if (!continueOnError) |
||||
return error; |
||||
|
||||
addError(results, *error); |
||||
continue; |
||||
} |
||||
|
||||
addResult(results, nullptr); |
||||
continue; |
||||
} |
||||
|
||||
if (method == METHOD_QUERY) { |
||||
Encodable::Map result; |
||||
const auto error = this->Query(operation.sql, operation.arguments, result); |
||||
|
||||
if (error) { |
||||
if (!continueOnError) |
||||
return error; |
||||
|
||||
addError(results, *error); |
||||
continue; |
||||
} |
||||
|
||||
addResult(results, result); |
||||
continue; |
||||
} |
||||
|
||||
if (method == METHOD_UPDATE) { |
||||
int updated = 0; |
||||
const auto error = this->Update(operation.sql, operation.arguments, updated); |
||||
|
||||
if (error) { |
||||
if (!continueOnError) |
||||
return error; |
||||
|
||||
addError(results, *error); |
||||
continue; |
||||
} |
||||
|
||||
addResult(results, updated); |
||||
continue; |
||||
} |
||||
} |
||||
|
||||
return std::nullopt; |
||||
} |
@ -0,0 +1,44 @@
|
||||
#include <flutter/logger.h> |
||||
#include <sqflite_aurora/logger.h> |
||||
|
||||
Logger::Logger(Level level, const std::string &tag) |
||||
: level(level) |
||||
, tag(tag) |
||||
, devnull(0) |
||||
{} |
||||
|
||||
Logger::Level Logger::LogLevel() const |
||||
{ |
||||
return this->level; |
||||
} |
||||
|
||||
void Logger::SetLogLevel(Level level) |
||||
{ |
||||
this->level = level; |
||||
} |
||||
|
||||
std::string Logger::Tag() const |
||||
{ |
||||
return this->tag; |
||||
} |
||||
|
||||
void Logger::SetTag(const std::string &tag) |
||||
{ |
||||
this->tag = tag; |
||||
} |
||||
|
||||
std::ostream &Logger::verb() |
||||
{ |
||||
if (this->level >= Level::Verbose) |
||||
return loginfo << (this->tag.empty() ? "" : "[" + this->tag + "] "); |
||||
|
||||
return this->devnull; |
||||
} |
||||
|
||||
std::ostream &Logger::sql() |
||||
{ |
||||
if (this->level >= Level::Sql) |
||||
return loginfo << (this->tag.empty() ? "" : "[" + this->tag + "] "); |
||||
|
||||
return this->devnull; |
||||
} |
@ -0,0 +1,619 @@
|
||||
#include <flutter/application.h> |
||||
#include <flutter/logger.h> |
||||
|
||||
#include <sqflite_aurora/constants.h> |
||||
#include <sqflite_aurora/sqflite_aurora_plugin.h> |
||||
|
||||
#include <filesystem> |
||||
#include <fstream> |
||||
|
||||
namespace { |
||||
|
||||
int64_t GetTransactionID(const Encodable &args) |
||||
{ |
||||
if (!args.HasKey(ARG_TRANSACTION_ID)) |
||||
return static_cast<int64_t>(Database::TransactionID::None); |
||||
|
||||
if (args[ARG_TRANSACTION_ID].IsNull()) |
||||
return static_cast<int64_t>(Database::TransactionID::None); |
||||
|
||||
if (!args[ARG_TRANSACTION_ID].IsInt()) |
||||
return static_cast<int64_t>(Database::TransactionID::None); |
||||
|
||||
return args[ARG_TRANSACTION_ID].GetInt(); |
||||
} |
||||
|
||||
Encodable::List GetSqlArguments(const Encodable &args) |
||||
{ |
||||
if (!args.HasKey(ARG_SQL_ARGUMENTS)) |
||||
return Encodable::List{}; |
||||
|
||||
if (args[ARG_SQL_ARGUMENTS].IsNull()) |
||||
return Encodable::List{}; |
||||
|
||||
if (!args[ARG_SQL_ARGUMENTS].IsList()) |
||||
return Encodable::List{}; |
||||
|
||||
return args[ARG_SQL_ARGUMENTS].GetList(); |
||||
} |
||||
|
||||
} /* namespace */ |
||||
|
||||
SqfliteAuroraPlugin::SqfliteAuroraPlugin() |
||||
: dbID(0) |
||||
, logger(Logger::Level::None, "sqflite") |
||||
{} |
||||
|
||||
void SqfliteAuroraPlugin::RegisterWithRegistrar(PluginRegistrar ®istrar) |
||||
{ |
||||
registrar.RegisterMethodChannel("com.tekartik.sqflite", |
||||
MethodCodecType::Standard, |
||||
[this](const MethodCall &call) { this->onMethodCall(call); }); |
||||
} |
||||
|
||||
void SqfliteAuroraPlugin::onMethodCall(const MethodCall &call) |
||||
{ |
||||
const auto &method = call.GetMethod(); |
||||
|
||||
if (method == METHOD_GET_PLATFORM_VERSION) { |
||||
this->onPlatformVersionCall(call); |
||||
return; |
||||
} |
||||
|
||||
if (method == METHOD_OPEN_DATABASE) { |
||||
this->onOpenDatabaseCall(call); |
||||
return; |
||||
} |
||||
|
||||
if (method == METHOD_CLOSE_DATABASE) { |
||||
this->onCloseDatabaseCall(call); |
||||
return; |
||||
} |
||||
|
||||
if (method == METHOD_DELETE_DATABASE) { |
||||
this->onDeleteDatabaseCall(call); |
||||
return; |
||||
} |
||||
|
||||
if (method == METHOD_DATABASE_EXISTS) { |
||||
this->onDatabaseExistsCall(call); |
||||
return; |
||||
} |
||||
|
||||
if (method == METHOD_GET_DATABASES_PATH) { |
||||
this->onGetDatabasesPathCall(call); |
||||
return; |
||||
} |
||||
|
||||
if (method == METHOD_OPTIONS) { |
||||
this->onOptionsCall(call); |
||||
return; |
||||
} |
||||
|
||||
if (method == METHOD_DEBUG) { |
||||
this->onDebugCall(call); |
||||
return; |
||||
} |
||||
|
||||
if (method == METHOD_EXECUTE) { |
||||
this->onExecuteCall(call); |
||||
return; |
||||
} |
||||
|
||||
if (method == METHOD_QUERY) { |
||||
this->onQueryCall(call); |
||||
return; |
||||
} |
||||
|
||||
if (method == METHOD_QUERY_CURSOR_NEXT) { |
||||
this->onQueryCursorNextCall(call); |
||||
return; |
||||
} |
||||
|
||||
if (method == METHOD_UPDATE) { |
||||
this->onUpdateCall(call); |
||||
return; |
||||
} |
||||
|
||||
if (method == METHOD_INSERT) { |
||||
this->onInsertCall(call); |
||||
return; |
||||
} |
||||
|
||||
if (method == METHOD_BATCH) { |
||||
this->onBatchCall(call); |
||||
return; |
||||
} |
||||
|
||||
this->success(call); |
||||
} |
||||
|
||||
void SqfliteAuroraPlugin::onPlatformVersionCall(const MethodCall &call) |
||||
{ |
||||
std::ifstream in("/etc/os-release"); |
||||
std::string line; |
||||
|
||||
while (in.is_open() && std::getline(in, line)) { |
||||
if (line.rfind("VERSION_ID=") != 0) |
||||
continue; |
||||
|
||||
this->success(call, "Aurora " + line.substr(11)); |
||||
return; |
||||
} |
||||
|
||||
this->success(call, "Aurora"); |
||||
} |
||||
|
||||
void SqfliteAuroraPlugin::onOpenDatabaseCall(const MethodCall &call) |
||||
{ |
||||
const auto &args = call.GetArguments(); |
||||
|
||||
const auto dbPath = args[ARG_PATH].GetString(); |
||||
const auto readOnly = args.HasKey(ARG_READ_ONLY) ? args[ARG_READ_ONLY].GetBoolean() : false; |
||||
|
||||
const auto inMemory = dbPath.empty() || dbPath == ":memory:"; |
||||
const auto singleton = args[ARG_SINGLE_INSTANCE].GetBoolean() && !inMemory; |
||||
|
||||
if (singleton) { |
||||
const auto db = this->databaseByPath(dbPath); |
||||
|
||||
if (db) { |
||||
if (db->IsOpen()) { |
||||
this->logger.verb() << "re-opened single instance database" |
||||
<< (db->IsInTransaction() ? "(in transaction) " : "") |
||||
<< db->ID() << " " << db->Path() << std::endl; |
||||
|
||||
this->success(call, makeOpenResult(db->ID(), true, db->IsInTransaction())); |
||||
return; |
||||
} |
||||
|
||||
this->logger.verb() << "single instance database " << db->Path() << " not opened" |
||||
<< std::endl; |
||||
} |
||||
} |
||||
|
||||
const auto db = std::make_shared<Database>(++dbID, dbPath, singleton, logger); |
||||
|
||||
this->asynq.Push([this, db, readOnly, call] { |
||||
this->logger.sql() << "open database " + db->Path() + " (ID=" << db->ID() << ")" |
||||
<< std::endl; |
||||
|
||||
const auto error = readOnly ? db->OpenReadOnly() : db->Open(); |
||||
if (error) { |
||||
this->error(call, ERROR_OPEN, db->Path(), *error); |
||||
return; |
||||
} |
||||
|
||||
this->databaseAdd(db); |
||||
this->success(call, makeOpenResult(db->ID(), false, false)); |
||||
}); |
||||
} |
||||
|
||||
void SqfliteAuroraPlugin::onCloseDatabaseCall(const MethodCall &call) |
||||
{ |
||||
const auto &args = call.GetArguments(); |
||||
const auto dbID = args[ARG_ID].GetInt(); |
||||
|
||||
const auto db = databaseByID(dbID); |
||||
|
||||
this->asynq.Push([this, db, dbID, call] { |
||||
if (!db) { |
||||
this->error(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); |
||||
return; |
||||
} |
||||
|
||||
this->logger.sql() << "closing database with ID=" << db->ID() << std::endl; |
||||
|
||||
const auto error = db->Close(); |
||||
if (error) { |
||||
this->error(call, ERROR_CLOSE, db->Path(), *error); |
||||
return; |
||||
} |
||||
|
||||
this->databaseRemove(db); |
||||
this->success(call); |
||||
}); |
||||
} |
||||
|
||||
void SqfliteAuroraPlugin::onDeleteDatabaseCall(const MethodCall &call) |
||||
{ |
||||
const auto &args = call.GetArguments(); |
||||
const auto dbPath = args[ARG_PATH].GetString(); |
||||
|
||||
const auto db = databaseByPath(dbPath); |
||||
|
||||
this->asynq.Push([this, db, dbPath, call] { |
||||
if (db) { |
||||
if (db->IsOpen()) { |
||||
this->logger.verb() |
||||
<< "close database " << db->Path() << " (ID=" << db->ID() << ")" << std::endl; |
||||
|
||||
const auto error = db->Close(); |
||||
if (error) { |
||||
this->error(call, ERROR_CLOSE, db->Path(), *error); |
||||
return; |
||||
} |
||||
} |
||||
|
||||
this->databaseRemove(db); |
||||
} |
||||
|
||||
if (std::filesystem::exists(dbPath)) { |
||||
this->logger.verb() << "delete not opened database " << dbPath << std::endl; |
||||
std::filesystem::remove(dbPath); |
||||
} |
||||
|
||||
this->success(call); |
||||
}); |
||||
} |
||||
|
||||
void SqfliteAuroraPlugin::onDatabaseExistsCall(const MethodCall &call) |
||||
{ |
||||
const auto &args = call.GetArguments(); |
||||
const auto dbPath = args[ARG_PATH].GetString(); |
||||
|
||||
this->success(call, std::filesystem::exists(dbPath)); |
||||
} |
||||
|
||||
void SqfliteAuroraPlugin::onGetDatabasesPathCall(const MethodCall &call) |
||||
{ |
||||
const auto home = std::getenv("HOME"); |
||||
|
||||
if (home == nullptr) { |
||||
this->error(call, ERROR_INTERNAL, "environment variable $HOME not found"); |
||||
return; |
||||
} |
||||
|
||||
const auto [orgname, appname] = Application::GetID(); |
||||
const auto directory = std::filesystem::path(home) / ".local/share" / orgname / appname; |
||||
|
||||
this->success(call, directory.generic_string()); |
||||
} |
||||
|
||||
void SqfliteAuroraPlugin::onOptionsCall(const MethodCall &call) |
||||
{ |
||||
const auto &args = call.GetArguments(); |
||||
const auto level = args[ARG_LOG_LEVEL].GetInt(); |
||||
|
||||
this->logger.SetLogLevel(static_cast<Logger::Level>(level)); |
||||
this->success(call); |
||||
} |
||||
|
||||
void SqfliteAuroraPlugin::onDebugCall(const MethodCall &call) |
||||
{ |
||||
const auto &args = call.GetArguments(); |
||||
const auto cmd = args[ARG_COMMAND].GetString(); |
||||
|
||||
std::lock_guard<std::mutex> lock(this->mutex); |
||||
Encodable::Map result; |
||||
|
||||
if (cmd == "get") { |
||||
if (this->logger.LogLevel() > Logger::Level::None) |
||||
result.emplace(ARG_LOG_LEVEL, static_cast<Encodable::Int>(this->logger.LogLevel())); |
||||
|
||||
if (!this->databases.empty()) { |
||||
Encodable::Map databases; |
||||
|
||||
for (const auto &[id, db] : this->databases) { |
||||
Encodable::Map info; |
||||
|
||||
info.emplace(ARG_PATH, db->Path()); |
||||
info.emplace(ARG_SINGLE_INSTANCE, db->IsSingleInstance()); |
||||
|
||||
if (db->LogLevel() > Logger::Level::None) |
||||
info.emplace(ARG_LOG_LEVEL, static_cast<Encodable::Int>(db->LogLevel())); |
||||
|
||||
databases.emplace(std::to_string(id), info); |
||||
} |
||||
|
||||
result.emplace(ARG_DATABASES, databases); |
||||
} |
||||
} |
||||
|
||||
this->success(call, result); |
||||
} |
||||
|
||||
void SqfliteAuroraPlugin::onExecuteCall(const MethodCall &call) |
||||
{ |
||||
const auto &args = call.GetArguments(); |
||||
|
||||
const auto dbID = args[ARG_ID].GetInt(); |
||||
const auto sql = args[ARG_SQL].GetString(); |
||||
const auto sqlArgs = GetSqlArguments(args); |
||||
const auto inTransactionChange = args.HasKey(ARG_IN_TRANSACTION) |
||||
? args[ARG_IN_TRANSACTION].GetBoolean() |
||||
: false; |
||||
const auto transactionID = GetTransactionID(args); |
||||
const auto enteringTransaction = inTransactionChange == true |
||||
&& transactionID == Database::TransactionID::None; |
||||
|
||||
const auto db = databaseByID(dbID); |
||||
|
||||
if (!db) { |
||||
this->error(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); |
||||
return; |
||||
} |
||||
|
||||
this->asynq.Push( |
||||
[this, db, sql, sqlArgs, inTransactionChange, enteringTransaction, transactionID, call] { |
||||
db->ProcessSqlCommand( |
||||
transactionID, |
||||
[this, db, sql, sqlArgs, inTransactionChange, enteringTransaction, call] { |
||||
if (enteringTransaction) |
||||
db->EnterInTransaction(); |
||||
|
||||
const auto error = db->Execute(sql, sqlArgs); |
||||
|
||||
if (error) { |
||||
db->LeaveTransaction(); |
||||
this->error(call, ERROR_INTERNAL, *error); |
||||
return; |
||||
} |
||||
|
||||
if (enteringTransaction) { |
||||
this->success(call, |
||||
Encodable::Map{ |
||||
{ARG_TRANSACTION_ID, db->CurrentTransactionID()}, |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
if (inTransactionChange == false) |
||||
db->LeaveTransaction(); |
||||
|
||||
this->success(call); |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
void SqfliteAuroraPlugin::onQueryCall(const MethodCall &call) |
||||
{ |
||||
const auto &args = call.GetArguments(); |
||||
|
||||
const auto dbID = args[ARG_ID].GetInt(); |
||||
const auto sql = args[ARG_SQL].GetString(); |
||||
const auto sqlArgs = GetSqlArguments(args); |
||||
const auto transactionID = GetTransactionID(args); |
||||
const auto pageSize = args.HasKey(ARG_CURSOR_PAGE_SIZE) ? args[ARG_CURSOR_PAGE_SIZE].GetInt() |
||||
: -1; |
||||
const auto db = databaseByID(dbID); |
||||
|
||||
if (!db) { |
||||
this->error(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); |
||||
return; |
||||
} |
||||
|
||||
this->asynq.Push([this, db, sql, sqlArgs, transactionID, pageSize, call] { |
||||
db->ProcessSqlCommand(transactionID, [this, db, sql, sqlArgs, pageSize, call] { |
||||
Encodable::Map result; |
||||
std::optional<std::string> error; |
||||
|
||||
if (pageSize <= 0) |
||||
error = db->Query(sql, sqlArgs, result); |
||||
else |
||||
error = db->QueryWithPageSize(sql, sqlArgs, pageSize, result); |
||||
|
||||
if (error) { |
||||
this->error(call, ERROR_INTERNAL, *error); |
||||
return; |
||||
} |
||||
|
||||
this->success(call, result); |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
void SqfliteAuroraPlugin::onQueryCursorNextCall(const MethodCall &call) |
||||
{ |
||||
const auto &args = call.GetArguments(); |
||||
|
||||
const auto dbID = args[ARG_ID].GetInt(); |
||||
const auto cursorID = args[ARG_CURSOR_ID].GetInt(); |
||||
const auto closeCursor = args.HasKey(ARG_CANCEL) ? args[ARG_CANCEL].GetBoolean() : false; |
||||
const auto transactionID = GetTransactionID(args); |
||||
|
||||
const auto db = databaseByID(dbID); |
||||
|
||||
if (!db) { |
||||
this->error(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); |
||||
return; |
||||
} |
||||
|
||||
this->asynq.Push([this, db, cursorID, closeCursor, transactionID, call] { |
||||
db->ProcessSqlCommand(transactionID, [this, db, cursorID, closeCursor, call] { |
||||
Encodable::Map result; |
||||
const auto error = db->QueryCursorNext(cursorID, closeCursor, result); |
||||
|
||||
if (error) { |
||||
this->error(call, ERROR_INTERNAL, *error); |
||||
return; |
||||
} |
||||
|
||||
this->success(call, result); |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
void SqfliteAuroraPlugin::onUpdateCall(const MethodCall &call) |
||||
{ |
||||
const auto &args = call.GetArguments(); |
||||
|
||||
const auto dbID = args[ARG_ID].GetInt(); |
||||
const auto sql = args[ARG_SQL].GetString(); |
||||
const auto sqlArgs = GetSqlArguments(args); |
||||
const auto transactionID = GetTransactionID(args); |
||||
|
||||
const auto db = databaseByID(dbID); |
||||
|
||||
if (!db) { |
||||
this->error(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); |
||||
return; |
||||
} |
||||
|
||||
this->asynq.Push([this, db, sql, sqlArgs, transactionID, call] { |
||||
db->ProcessSqlCommand(transactionID, [this, db, sql, sqlArgs, call] { |
||||
int updated = 0; |
||||
const auto error = db->Update(sql, sqlArgs, updated); |
||||
|
||||
if (error) { |
||||
this->error(call, ERROR_INTERNAL, *error); |
||||
return; |
||||
} |
||||
|
||||
this->success(call, updated); |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
void SqfliteAuroraPlugin::onInsertCall(const MethodCall &call) |
||||
{ |
||||
const auto &args = call.GetArguments(); |
||||
|
||||
const auto dbID = args[ARG_ID].GetInt(); |
||||
const auto sql = args[ARG_SQL].GetString(); |
||||
const auto sqlArgs = GetSqlArguments(args); |
||||
const auto transactionID = GetTransactionID(args); |
||||
|
||||
const auto db = databaseByID(dbID); |
||||
|
||||
if (!db) { |
||||
this->error(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); |
||||
return; |
||||
} |
||||
|
||||
this->asynq.Push([this, db, sql, sqlArgs, transactionID, call] { |
||||
db->ProcessSqlCommand(transactionID, [this, db, sql, sqlArgs, call] { |
||||
int insertID = 0; |
||||
const auto error = db->Insert(sql, sqlArgs, insertID); |
||||
|
||||
if (error) { |
||||
this->error(call, ERROR_INTERNAL, *error); |
||||
return; |
||||
} |
||||
|
||||
if (insertID == 0) |
||||
this->success(call); |
||||
else |
||||
this->success(call, insertID); |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
void SqfliteAuroraPlugin::onBatchCall(const MethodCall &call) |
||||
{ |
||||
const auto &args = call.GetArguments(); |
||||
|
||||
const auto dbID = args[ARG_ID].GetInt(); |
||||
const auto &operations = args[ARG_OPERATIONS].GetList(); |
||||
const auto noResult = args.HasKey(ARG_NO_RESULT) ? args[ARG_NO_RESULT].GetBoolean() : false; |
||||
const auto continueOnError = args.HasKey(ARG_CONTINUE_ON_ERROR) |
||||
? args[ARG_CONTINUE_ON_ERROR].GetBoolean() |
||||
: false; |
||||
const auto transactionID = GetTransactionID(args); |
||||
|
||||
const auto db = databaseByID(dbID); |
||||
|
||||
if (!db) { |
||||
this->error(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); |
||||
return; |
||||
} |
||||
|
||||
std::vector<Database::Operation> dbOperations; |
||||
|
||||
for (const auto &operation : operations) { |
||||
const auto method = operation[ARG_METHOD].GetString(); |
||||
const auto sql = operation[ARG_SQL].GetString(); |
||||
const auto sqlArgs = GetSqlArguments(operation); |
||||
|
||||
dbOperations.emplace_back(Database::Operation{method, sql, sqlArgs}); |
||||
} |
||||
|
||||
this->asynq.Push([this, db, dbOperations, transactionID, continueOnError, noResult, call] { |
||||
const auto command = [this, db, dbOperations, continueOnError, noResult, call] { |
||||
Encodable::List results; |
||||
const auto error = db->Batch(dbOperations, continueOnError, results); |
||||
if (error) { |
||||
this->error(call, ERROR_INTERNAL, *error); |
||||
return; |
||||
} |
||||
|
||||
if (noResult) |
||||
this->success(call); |
||||
else |
||||
this->success(call, results); |
||||
}; |
||||
|
||||
db->ProcessSqlCommand(transactionID, command); |
||||
}); |
||||
} |
||||
|
||||
std::shared_ptr<Database> SqfliteAuroraPlugin::databaseByPath(const std::string &path) |
||||
{ |
||||
std::lock_guard<std::mutex> lock(this->mutex); |
||||
|
||||
if (!this->singletonDatabases.count(path)) |
||||
return nullptr; |
||||
|
||||
return this->singletonDatabases.at(path); |
||||
} |
||||
|
||||
std::shared_ptr<Database> SqfliteAuroraPlugin::databaseByID(int64_t id) |
||||
{ |
||||
std::lock_guard<std::mutex> lock(this->mutex); |
||||
|
||||
if (!this->databases.count(id)) |
||||
return nullptr; |
||||
|
||||
return this->databases.at(id); |
||||
} |
||||
|
||||
void SqfliteAuroraPlugin::databaseRemove(std::shared_ptr<Database> db) |
||||
{ |
||||
std::lock_guard<std::mutex> lock(this->mutex); |
||||
|
||||
if (db->IsSingleInstance()) |
||||
this->singletonDatabases.erase(db->Path()); |
||||
|
||||
this->databases.erase(db->ID()); |
||||
} |
||||
|
||||
void SqfliteAuroraPlugin::databaseAdd(std::shared_ptr<Database> db) |
||||
{ |
||||
std::lock_guard<std::mutex> lock(this->mutex); |
||||
|
||||
if (db->IsSingleInstance()) |
||||
this->singletonDatabases.emplace(db->Path(), db); |
||||
|
||||
this->databases.emplace(db->ID(), db); |
||||
} |
||||
|
||||
void SqfliteAuroraPlugin::success(const MethodCall &call, const Encodable &result) |
||||
{ |
||||
call.SendSuccessResponse(result); |
||||
} |
||||
|
||||
void SqfliteAuroraPlugin::error(const MethodCall &call, |
||||
const std::string &error, |
||||
const std::string &message, |
||||
const std::string &desc, |
||||
const Encodable &details) |
||||
{ |
||||
call.SendErrorResponse(ERROR_SQFLITE, |
||||
error + ": " + message + (desc.empty() ? "" : " (" + desc + ")"), |
||||
details); |
||||
} |
||||
|
||||
Encodable::Map SqfliteAuroraPlugin::makeOpenResult(int64_t dbID, |
||||
bool recovered, |
||||
bool recoveredInTransaction) |
||||
{ |
||||
Encodable::Map result = {{ARG_ID, dbID}}; |
||||
|
||||
if (recovered) |
||||
result.emplace(ARG_RECOVERED, true); |
||||
|
||||
if (recoveredInTransaction) |
||||
result.emplace(ARG_RECOVERED_IN_TRANSACTION, true); |
||||
|
||||
return result; |
||||
} |
After Width: | Height: | Size: 101 KiB |
@ -0,0 +1,45 @@
|
||||
# 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/ |
||||
|
||||
# Symbolication related |
||||
app.*.symbols |
||||
|
||||
# Obfuscation related |
||||
app.*.map.json |
||||
|
||||
# Android Studio will place build artifacts here |
||||
/pubspec.lock |
||||
/android/app/debug |
||||
/android/app/profile |
||||
/android/app/release |
@ -0,0 +1,25 @@
|
||||
BSD 2-Clause License |
||||
|
||||
Copyright (c) 2019, Alexandre Roux Tekartik |
||||
All rights reserved. |
||||
|
||||
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. |
||||
|
||||
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. |
@ -0,0 +1,9 @@
|
||||
# Sqflite example for Aurora OS |
||||
|
||||
Demonstrates how to use the `sqflite_aurora` plugin. |
||||
|
||||
## Building |
||||
|
||||
```shell |
||||
$ flutter build aurora [--release|--debug|--profile] |
||||
``` |
@ -0,0 +1,87 @@
|
||||
include: package:flutter_lints/flutter.yaml |
||||
|
||||
analyzer: |
||||
language: |
||||
strict-casts: true |
||||
strict-inference: true |
||||
|
||||
errors: |
||||
missing_required_param: warning |
||||
missing_return: warning |
||||
todo: ignore |
||||
included_file_warning: ignore |
||||
|
||||
linter: |
||||
rules: |
||||
- always_declare_return_types |
||||
- avoid_dynamic_calls |
||||
- avoid_empty_else |
||||
- avoid_relative_lib_imports |
||||
- avoid_shadowing_type_parameters |
||||
- avoid_slow_async_io |
||||
- avoid_types_as_parameter_names |
||||
- await_only_futures |
||||
- camel_case_extensions |
||||
- camel_case_types |
||||
- cancel_subscriptions |
||||
- curly_braces_in_flow_control_structures |
||||
- directives_ordering |
||||
- empty_catches |
||||
- hash_and_equals |
||||
- iterable_contains_unrelated_type |
||||
- list_remove_unrelated_type |
||||
- no_adjacent_strings_in_list |
||||
- no_duplicate_case_values |
||||
- non_constant_identifier_names |
||||
- omit_local_variable_types |
||||
- package_api_docs |
||||
- package_prefixed_library_names |
||||
- prefer_generic_function_type_aliases |
||||
- prefer_is_empty |
||||
- prefer_is_not_empty |
||||
- prefer_iterable_whereType |
||||
- prefer_single_quotes |
||||
- prefer_typing_uninitialized_variables |
||||
- sort_child_properties_last |
||||
- test_types_in_equals |
||||
- throw_in_finally |
||||
- unawaited_futures |
||||
- unnecessary_null_aware_assignments |
||||
- unnecessary_statements |
||||
- unrelated_type_equality_checks |
||||
- unsafe_html |
||||
- valid_regexps |
||||
|
||||
- constant_identifier_names |
||||
- control_flow_in_finally |
||||
- empty_statements |
||||
- implementation_imports |
||||
- overridden_fields |
||||
- package_names |
||||
- prefer_const_constructors |
||||
- prefer_initializing_formals |
||||
- prefer_void_to_null |
||||
|
||||
- always_require_non_null_named_parameters |
||||
- annotate_overrides |
||||
- avoid_init_to_null |
||||
- avoid_null_checks_in_equality_operators |
||||
- avoid_return_types_on_setters |
||||
- empty_constructor_bodies |
||||
- library_names |
||||
- library_prefixes |
||||
- prefer_adjacent_string_concatenation |
||||
- prefer_collection_literals |
||||
- prefer_contains |
||||
- prefer_equal_for_default_values |
||||
- slash_for_doc_comments |
||||
- type_init_formals |
||||
- unnecessary_const |
||||
- unnecessary_new |
||||
- unnecessary_null_in_if_null_operators |
||||
- use_rethrow_when_possible |
||||
|
||||
- public_member_api_docs |
||||
|
||||
- sort_constructors_first |
||||
- sort_unnamed_constructors_first |
@ -0,0 +1 @@
|
||||
flutter/ephemeral |
@ -0,0 +1,47 @@
|
||||
cmake_minimum_required(VERSION 3.10) |
||||
project(com.example.sqflite_aurora_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) |
@ -0,0 +1,12 @@
|
||||
[Desktop Entry] |
||||
Type=Application |
||||
Name=Sqflite Example |
||||
Comment=Demonstrates how to use the sqflite_aurora plugin. |
||||
Icon=com.example.sqflite_aurora_example |
||||
Exec=/usr/bin/com.example.sqflite_aurora_example |
||||
X-Nemo-Application-Type=silica-qt5 |
||||
|
||||
[X-Application] |
||||
Permissions= |
||||
OrganizationName=com.example |
||||
ApplicationName=sqflite_aurora_example |
@ -0,0 +1,16 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include <flutter/application.h> |
||||
#include <sqflite_aurora/sqflite_aurora_plugin.h> |
||||
|
||||
#include "generated_plugin_registrant.h" |
||||
|
||||
void RegisterPlugins() { |
||||
Application::RegisterPlugins({ |
||||
std::make_shared<SqfliteAuroraPlugin>(), |
||||
}); |
||||
} |
@ -0,0 +1,12 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifndef GENERATED_PLUGIN_REGISTRANT |
||||
#define GENERATED_PLUGIN_REGISTRANT |
||||
|
||||
void RegisterPlugins(); |
||||
|
||||
#endif /* GENERATED_PLUGIN_REGISTRANT */ |
@ -0,0 +1,31 @@
|
||||
# |
||||
# Generated file, do not edit. |
||||
# |
||||
set(ROOT_PROJECT_BINARY_DIR "${PROJECT_BINARY_DIR}") |
||||
|
||||
function(add_library TARGET) |
||||
_add_library(${TARGET} ${ARGN}) |
||||
|
||||
if(NOT "${TARGET}" MATCHES "^PkgConfig::.*") |
||||
add_custom_command(TARGET ${TARGET} POST_BUILD |
||||
COMMAND ${CMAKE_COMMAND} -E copy |
||||
"$<TARGET_FILE:${TARGET}>" |
||||
"${ROOT_PROJECT_BINARY_DIR}/bundle/lib/$<TARGET_FILE_NAME:${TARGET}>") |
||||
endif(NOT "${TARGET}" MATCHES "^PkgConfig::.*") |
||||
endfunction() |
||||
|
||||
list(APPEND FLUTTER_PLATFORM_PLUGIN_LIST |
||||
sqflite_aurora |
||||
) |
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST |
||||
) |
||||
|
||||
foreach(PLUGIN ${FLUTTER_PLATFORM_PLUGIN_LIST}) |
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${PLUGIN}/aurora plugins/${PLUGIN}) |
||||
target_link_libraries(${BINARY_NAME} PRIVATE ${PLUGIN}_platform_plugin) |
||||
endforeach(PLUGIN) |
||||
|
||||
foreach(FFI_PLUGIN ${FLUTTER_FFI_PLUGIN_LIST}) |
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${FFI_PLUGIN}/aurora plugins/${FFI_PLUGIN}) |
||||
endforeach(FFI_PLUGIN) |
After Width: | Height: | Size: 9.7 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 6.5 KiB |
@ -0,0 +1,10 @@
|
||||
#include <flutter/application.h> |
||||
#include "generated_plugin_registrant.h" |
||||
|
||||
int main(int argc, char *argv[]) { |
||||
Application::Initialize(argc, argv); |
||||
Application::SetPixelRatio(1.8); |
||||
RegisterPlugins(); |
||||
Application::Launch(); |
||||
return 0; |
||||
} |