diff --git a/.env.example b/.env.example
index deba5fa..77d0676 100644
--- a/.env.example
+++ b/.env.example
@@ -4,6 +4,8 @@ POSTGRES_PORT=
POSTGRES_DB=
POSTGRES_HOST=
WORKER_API_KEY=
+
+HOSTNAME=aeris.com
WORKER_API_URL=
WORKER_URL=
DISCORD_CLIENT_ID=
@@ -18,3 +20,4 @@ SPOTIFY_CLIENT_ID=
SPOTIFY_SECRET=
ANILIST_SECRET=
ANILIST_CLIENT_ID=
+BACK_URL=
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 7a122fc..1a8dccc 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -20,7 +20,6 @@ jobs:
- name: Run Docker
run: docker run -v $PWD:/dist aeris_mobile_build
- name: Upload build artifact
- if: github.ref == 'refs/head/master'
uses: actions/upload-artifact@v2
with:
name: aeris_apk
diff --git a/api/services/anilist.json b/api/services/anilist.json
index 54aab94..44166cf 100644
--- a/api/services/anilist.json
+++ b/api/services/anilist.json
@@ -3,7 +3,7 @@
"actions": [],
"reactions": [
{
- "name": "UpdateAbout",
+ "name": "Anilist_UpdateAbout",
"description": {
"en": "Update the about you section.",
"fr": "Mets à jour votre section \"À propos de moi\"."
@@ -25,7 +25,7 @@
"returns": []
},
{
- "name": "ToggleFavourite",
+ "name": "Anilist_ToggleFavourite",
"description": {
"en": "Add or remove an anime from your favorite.",
"fr": "Ajoute ou retire un animé de vos favoris."
diff --git a/api/services/spotify.json b/api/services/spotify.json
index d5e1d19..5d4c9df 100644
--- a/api/services/spotify.json
+++ b/api/services/spotify.json
@@ -69,6 +69,7 @@
],
"reactions": [
{
+<<<<<<< HEAD
"name": "PlayTrack",
"description": {
"en": "Play a track",
@@ -78,6 +79,10 @@
"en": "Play a track",
"fr": "Joue une musique"
},
+=======
+ "name": "Spotify_PlayTrack",
+ "description": "Play a track",
+>>>>>>> 26566154676c8e279c3615522129e61b851c75a9
"params": [
{
"name": "artist",
@@ -134,6 +139,7 @@
"returns": []
},
{
+<<<<<<< HEAD
"name": "AddTrackToLibrary",
"description": {
"en": "Add a track to library",
@@ -143,6 +149,10 @@
"en": "Add a song to library",
"fr": "Ajoute une musique à votre librarie"
},
+=======
+ "name": "Spotify_AddTrackToLibrary",
+ "description": "Add a track to library",
+>>>>>>> 26566154676c8e279c3615522129e61b851c75a9
"params": [
{
"name": "artist",
diff --git a/api/src/Api/OIDC.hs b/api/src/Api/OIDC.hs
index 5b0244f..fd96da9 100644
--- a/api/src/Api/OIDC.hs
+++ b/api/src/Api/OIDC.hs
@@ -40,34 +40,34 @@ urlHandler :: Service -> Maybe String -> AppM NoContent
urlHandler _ Nothing = throwError err400
urlHandler Anilist (Just r) = do
clientId <- liftIO $ envAsString "ANILIST_CLIENT_ID" ""
- backRedirect <- liftIO $ envAsString "BACK_REDIRECT_URL" ""
+ backRedirect <- liftIO $ envAsString "BACK_URL" ""
throwError $ err302 { errHeaders =
- [("Location", B8.pack $ "https://anilist.co/api/v2/oauth/authorize?client_id=" ++ clientId ++ "&response_type=code&redirect_uri=" ++ backRedirect ++ "&state=" ++ r)] }
+ [("Location", B8.pack $ "https://anilist.co/api/v2/oauth/authorize?client_id=" ++ clientId ++ "&response_type=code&redirect_uri=" ++ backRedirect ++ "auth/redirect" ++ "&state=" ++ r)] }
urlHandler Discord (Just r) = do
clientId <- liftIO $ envAsString "DISCORD_CLIENT_ID" ""
- backRedirect <- liftIO $ envAsString "BACK_REDIRECT_URL" ""
+ backRedirect <- liftIO $ envAsString "BACK_URL" ""
throwError $ err302 { errHeaders =
- [("Location", B8.pack $ "https://discord.com/api/oauth2/authorize?response_type=code&scope=identify&client_id=" ++ clientId ++ "&response_type=code&redirect_uri=" ++ backRedirect ++ "&state=" ++ r)] }
+ [("Location", B8.pack $ "https://discord.com/api/oauth2/authorize?response_type=code&scope=identify%20guilds%20messages.read%20activities.write%20webhook.incoming&client_id=" ++ clientId ++ "&response_type=code&redirect_uri=" ++ backRedirect ++ "auth/redirect" ++ "&state=" ++ r)] }
urlHandler Google (Just r) = do
clientId <- liftIO $ envAsString "GOOGLE_CLIENT_ID" ""
- backRedirect <- liftIO $ envAsString "BACK_REDIRECT_URL" ""
+ backRedirect <- liftIO $ envAsString "BACK_URL" ""
throwError $ err302 { errHeaders =
- [("Location", B8.pack $ "https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/youtube.force-ssl&access_type=offline&prompt=consent&include_granted_scopes=true&response_type=code&client_id=" ++ clientId ++ "&redirect_uri=" ++ backRedirect ++ "&state=" ++ r)] }
+ [("Location", B8.pack $ "https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/youtube.force-ssl&access_type=offline&prompt=consent&include_granted_scopes=true&response_type=code&client_id=" ++ clientId ++ "&redirect_uri=" ++ backRedirect ++ "auth/redirect" ++ "&state=" ++ r)] }
urlHandler Twitter (Just r) = do
clientId <- liftIO $ envAsString "TWITTER_CLIENT_ID" ""
- backRedirect <- liftIO $ envAsString "BACK_REDIRECT_URL" ""
+ backRedirect <- liftIO $ envAsString "BACK_URL" ""
throwError $ err302 { errHeaders =
- [("Location", B8.pack $ "https://twitter.com/i/oauth2/authorize?response_type=code&scope=like.write like.read follows.read follows.write offline.access tweet.read tweet.write&code_challenge=challenge&code_challenge_method=plain&client_id=" ++ clientId ++ "&redirect_uri=" ++ backRedirect ++ "&state=" ++ r)] }
+ [("Location", B8.pack $ "https://twitter.com/i/oauth2/authorize?response_type=code&scope=like.write like.read follows.read follows.write offline.access tweet.read tweet.write&code_challenge=challenge&code_challenge_method=plain&client_id=" ++ clientId ++ "&redirect_uri=" ++ backRedirect ++ "auth/redirect" ++ "&state=" ++ r)] }
urlHandler Spotify (Just r) = do
clientId <- liftIO $ envAsString "SPOTIFY_CLIENT_ID" ""
- backRedirect <- liftIO $ envAsString "BACK_REDIRECT_URL" ""
+ backRedirect <- liftIO $ envAsString "BACK_URL" ""
throwError $ err302 { errHeaders =
- [("Location", B8.pack $ "https://accounts.spotify.com/authorize?response_type=code&scope=user-library-read&client_id=" ++ clientId ++ "&redirect_uri=" ++ backRedirect ++ "&state=" ++ r)] }
+ [("Location", B8.pack $ "https://accounts.spotify.com/authorize?response_type=code&scope=user-library-read&client_id=" ++ clientId ++ "&redirect_uri=" ++ backRedirect ++ "auth/redirect" ++ "&state=" ++ r)] }
urlHandler Github (Just r) = do
clientId <- liftIO $ envAsString "GITHUB_CLIENT_ID" ""
- backRedirect <- liftIO $ envAsString "BACK_REDIRECT_URL" ""
+ backRedirect <- liftIO $ envAsString "BACK_URL" ""
throwError $ err302 { errHeaders =
- [("Location", B8.pack $ "https://github.com/login/oauth/authorize?response_type=code&scope=repo&client_id=" ++ clientId ++ "&redirect_uri=" ++ backRedirect ++ "&state=" ++ r)] }
+ [("Location", B8.pack $ "https://github.com/login/oauth/authorize?response_type=code&scope=repo&client_id=" ++ clientId ++ "&redirect_uri=" ++ backRedirect ++ "auth/redirect" ++ "&state=" ++ r)] }
servicesHandler :: AuthRes -> AppM [String]
servicesHandler (Authenticated (User uid name slug)) = do
diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml
index 2f49579..45d7529 100644
--- a/docker-compose.dev.yml
+++ b/docker-compose.dev.yml
@@ -19,6 +19,7 @@ services:
depends_on:
- "db"
environment:
+ - BACK_URL=${BACK_URL}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_HOST=${POSTGRES_HOST}
@@ -59,7 +60,6 @@ services:
- ANILIST_SECRET=${ANILIST_SECRET}
- WORKER_API_URL=${WORKER_API_URL}
- WORKER_API_KEY=${WORKER_API_KEY}
-
volumes:
apk:
cache:
diff --git a/docker-compose.yml b/docker-compose.yml
index ef75283..feedd51 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -42,6 +42,7 @@ services:
- POSTGRES_PORT=${POSTGRES_PORT}
- WORKER_API_KEY=${WORKER_API_KEY}
- WORKER_URL=${WORKER_URL}
+ - BACK_URL=${BACK_URL}
- DISCORD_CLIENT_ID=${DISCORD_CLIENT_ID}
- DISCORD_SECRET=${DISCORD_SECRET}
- GITHUB_CLIENT_ID=${GITHUB_CLIENT_ID}
diff --git a/mobile/Dockerfile b/mobile/Dockerfile
index a12dc0e..22c42db 100644
--- a/mobile/Dockerfile
+++ b/mobile/Dockerfile
@@ -21,5 +21,5 @@ RUN flutter gen-l10n
RUN flutter pub run flutter_launcher_icons:main
# Generate native splashscreen
RUN flutter pub run flutter_native_splash:create
-RUN flutter build apk lib/src/main.dart
+RUN flutter build apk lib/main.dart
CMD cp ./build/app/outputs/flutter-apk/app-release.apk /dist/aeris_android.apk
diff --git a/mobile/android/app/src/debug/AndroidManifest.xml b/mobile/android/app/src/debug/AndroidManifest.xml
index dbedc5d..704f300 100644
--- a/mobile/android/app/src/debug/AndroidManifest.xml
+++ b/mobile/android/app/src/debug/AndroidManifest.xml
@@ -1,7 +1,45 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mobile/android/app/src/main/AndroidManifest.xml b/mobile/android/app/src/main/AndroidManifest.xml
index d4912bf..704f300 100644
--- a/mobile/android/app/src/main/AndroidManifest.xml
+++ b/mobile/android/app/src/main/AndroidManifest.xml
@@ -25,6 +25,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/mobile/ios/Podfile.lock b/mobile/ios/Podfile.lock
index fafbab7..fae8f70 100644
--- a/mobile/ios/Podfile.lock
+++ b/mobile/ios/Podfile.lock
@@ -1,10 +1,14 @@
PODS:
- Flutter (1.0.0)
+ - flutter_keyboard_visibility (0.0.1):
+ - Flutter
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
- path_provider_ios (0.0.1):
- Flutter
+ - shared_preferences_ios (0.0.1):
+ - Flutter
- sqflite (0.0.2):
- Flutter
- FMDB (>= 2.7.5)
@@ -13,7 +17,9 @@ PODS:
DEPENDENCIES:
- Flutter (from `Flutter`)
+ - flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
+ - shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
@@ -24,8 +30,12 @@ SPEC REPOS:
EXTERNAL SOURCES:
Flutter:
:path: Flutter
+ flutter_keyboard_visibility:
+ :path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
path_provider_ios:
:path: ".symlinks/plugins/path_provider_ios/ios"
+ shared_preferences_ios:
+ :path: ".symlinks/plugins/shared_preferences_ios/ios"
sqflite:
:path: ".symlinks/plugins/sqflite/ios"
url_launcher_ios:
@@ -33,8 +43,10 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
+ flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
path_provider_ios: 7d7ce634493af4477d156294792024ec3485acd5
+ shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
diff --git a/mobile/ios/Runner.xcodeproj/project.pbxproj b/mobile/ios/Runner.xcodeproj/project.pbxproj
index 4fb782a..3b5299a 100644
--- a/mobile/ios/Runner.xcodeproj/project.pbxproj
+++ b/mobile/ios/Runner.xcodeproj/project.pbxproj
@@ -18,6 +18,7 @@
/* Begin PBXFileReference section */
0B9CFEF16F77B4F2467EF56A /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
+ 0C6C3D7227D0D7C100B12C20 /* RunnerDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerDebug.entitlements; sourceTree = ""; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
@@ -99,6 +100,7 @@
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
+ 0C6C3D7227D0D7C100B12C20 /* RunnerDebug.entitlements */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
@@ -217,7 +219,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
+ shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n";
};
755B6DB6A94E09EAD68F291E /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
@@ -248,7 +250,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
+ shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
};
/* End PBXShellScriptBuildPhase section */
@@ -476,6 +478,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/RunnerDebug.entitlements;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = HJ45QP4WWR;
ENABLE_BITCODE = NO;
diff --git a/mobile/ios/Runner/Assets.xcassets/BrandingImage.imageset/Contents.json b/mobile/ios/Runner/Assets.xcassets/BrandingImage.imageset/Contents.json
index 7f6f7e7..1271227 100644
--- a/mobile/ios/Runner/Assets.xcassets/BrandingImage.imageset/Contents.json
+++ b/mobile/ios/Runner/Assets.xcassets/BrandingImage.imageset/Contents.json
@@ -1,17 +1,17 @@
{
"images" : [
{
- "filename" : "icon.jpg",
+ "filename" : "BrandingImage.png",
"idiom" : "universal",
"scale" : "1x"
},
{
- "filename" : "icon-1.jpg",
+ "filename" : "BrandingImage@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
- "filename" : "icon-2.jpg",
+ "filename" : "BrandingImage@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
diff --git a/mobile/ios/Runner/Info-Debug.plist b/mobile/ios/Runner/Info-Debug.plist
index 6cdf697..6002f7c 100644
--- a/mobile/ios/Runner/Info-Debug.plist
+++ b/mobile/ios/Runner/Info-Debug.plist
@@ -47,5 +47,20 @@
UIViewControllerBasedStatusBarAppearance
+ FlutterDeepLinkingEnabled
+
+ CFBundleURLTypes
+
+
+ CFBundleTypeRole
+ Editor
+ CFBundleURLName
+ arthichaud.me
+ CFBundleURLSchemes
+
+ aeris
+
+
+
diff --git a/mobile/ios/Runner/Info-Release.plist b/mobile/ios/Runner/Info-Release.plist
index f759f12..edf6e96 100644
--- a/mobile/ios/Runner/Info-Release.plist
+++ b/mobile/ios/Runner/Info-Release.plist
@@ -45,5 +45,20 @@
UIStatusBarHidden
+ FlutterDeepLinkingEnabled
+
+ CFBundleURLTypes
+
+
+ CFBundleTypeRole
+ Editor
+ CFBundleURLName
+ arthichaud.me
+ CFBundleURLSchemes
+
+ aeris
+
+
+
\ No newline at end of file
diff --git a/mobile/ios/Runner/RunnerDebug.entitlements b/mobile/ios/Runner/RunnerDebug.entitlements
new file mode 100644
index 0000000..3fb05ea
--- /dev/null
+++ b/mobile/ios/Runner/RunnerDebug.entitlements
@@ -0,0 +1,8 @@
+
+
+
+
+ com.apple.developer.default-data-protection
+ NSFileProtectionComplete
+
+
diff --git a/mobile/lib/l10n/app_en.arb b/mobile/lib/l10n/app_en.arb
index cb6d5bf..382a4b8 100644
--- a/mobile/lib/l10n/app_en.arb
+++ b/mobile/lib/l10n/app_en.arb
@@ -36,5 +36,12 @@
"pipelineFormMisingAction": "You must select at least a trigger and a reaction",
"logoutWarningMessage": "You are about to logout, are you sure?",
"warning": "Warning",
- "cancel": "Cancel"
+ "cancel": "Cancel",
+ "errorOnSignup": "An error occured while signing you up, please try again",
+ "loading": "Loading...",
+ "invalidUrl": "Invalid URL",
+ "tryToConnect": "Try to connect",
+ "routeToApi": "Route to API",
+ "setupAPIRoute": "Setup API Route",
+ "paramInheritTip": "To inherit parameters from previous actions, type '{' in the text field and tap on the choosen parameter"
}
\ No newline at end of file
diff --git a/mobile/lib/l10n/app_fr.arb b/mobile/lib/l10n/app_fr.arb
index 3a54dbc..776233e 100644
--- a/mobile/lib/l10n/app_fr.arb
+++ b/mobile/lib/l10n/app_fr.arb
@@ -6,8 +6,8 @@
"today": "Aujourd'hui",
"nameOfThePipeline": "Nom de la pipeline",
"addReaction": "Ajouter une Reaction",
- "addTrigger": "Ajouter un Déclancheur",
- "setupTrigger": "Gérer une Déclancheur",
+ "addTrigger": "Ajouter un déclencheur",
+ "setupTrigger": "Gérer un déclencheur",
"setupReaction": "Gérer une Réaction",
"action": "Action",
"reactions": "Réactions",
@@ -33,8 +33,15 @@
"dangerZone": "Zone dangereuse",
"createNewPipeline": "Créer une nouvelle pipeline",
"save": "Enregistrer",
- "pipelineFormMisingAction": "Vous devez selectionner au moins un déclancheur et une réaction",
+ "pipelineFormMisingAction": "Vous devez selectionner au moins un déclencheur et une réaction",
"logoutWarningMessage": "Êtes-vous sûr(e) de voulour vous déconnecter d'Aeris?",
"warning": "Attention",
- "cancel": "Annuler"
+ "cancel": "Annuler",
+ "errorOnSignup": "Une erreur est survenue, veuillez réessayer",
+ "loading": "Chargement...",
+ "invalidUrl": "URL invalide",
+ "tryToConnect": "Tester la connection",
+ "routeToApi": "Route de l'API",
+ "setupAPIRoute": "Choisir la route de l'API",
+ "paramInheritTip": "Afin d'hériter de variables venant d'actions précedentes, entrez '{' dans un champ et choisissez la valeur"
}
\ No newline at end of file
diff --git a/mobile/lib/src/main.dart b/mobile/lib/main.dart
similarity index 65%
rename from mobile/lib/src/main.dart
rename to mobile/lib/main.dart
index 8e1f8a5..4529b27 100644
--- a/mobile/lib/src/main.dart
+++ b/mobile/lib/main.dart
@@ -1,8 +1,10 @@
import 'package:aeris/src/aeris_api.dart';
+import 'package:aeris/src/providers/action_catalogue_provider.dart';
+import 'package:aeris/src/views/authorization_page.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:form_builder_validators/localization/l10n.dart';
import 'package:aeris/src/providers/pipelines_provider.dart';
-import 'package:aeris/src/providers/user_services_provider.dart';
+import 'package:aeris/src/providers/services_provider.dart';
import 'package:aeris/src/views/startup_page.dart';
import 'package:aeris/src/views/login_page.dart';
import 'package:aeris/src/views/home_page.dart';
@@ -11,13 +13,19 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:get_it/get_it.dart';
+import 'package:shared_preferences/shared_preferences.dart';
-void main() {
+void main() async {
+ WidgetsFlutterBinding.ensureInitialized();
+ SharedPreferences prefs = await SharedPreferences.getInstance();
+ GetIt.I.registerSingleton(prefs);
AerisAPI interface = AerisAPI();
GetIt.I.registerSingleton(interface);
+ await interface.restoreConnection();
runApp(MultiProvider(providers: [
ChangeNotifierProvider(create: (_) => PipelineProvider()),
- ChangeNotifierProvider(create: (_) => UserServiceProvider())
+ ChangeNotifierProvider(create: (_) => ServiceProvider()),
+ ChangeNotifierProvider(create: (_) => ActionCatalogueProvider(), lazy: false)
], child: const Aeris()));
}
@@ -48,22 +56,23 @@ class Aeris extends StatelessWidget {
'/login': () => const LoginPage(),
'/home': () => const HomePage(),
};
+
return PageRouteBuilder(
opaque: false,
settings: settings,
- pageBuilder: (_, __, ___) => routes[settings.name].call(),
+ pageBuilder: (_, __, ___) {
+ if (settings.name!.startsWith('/authorization')) {
+ return const AuthorizationPage();
+ }
+ return routes[settings.name].call();
+ },
transitionDuration: const Duration(milliseconds: 350),
- transitionsBuilder: (context, animation, secondaryAnimation, child) =>
- SlideTransition(
- child: child,
- position: animation.drive(
- Tween(
- begin: const Offset(1.0, 0.0),
- end: Offset.zero
- )
- )
- )
- );
+ transitionsBuilder: (context, animation, secondaryAnimation,
+ child) =>
+ SlideTransition(
+ child: child,
+ position: animation.drive(Tween(
+ begin: const Offset(1.0, 0.0), end: Offset.zero))));
});
}
}
diff --git a/mobile/lib/src/aeris_api.dart b/mobile/lib/src/aeris_api.dart
index 5abf6fe..e89f18e 100644
--- a/mobile/lib/src/aeris_api.dart
+++ b/mobile/lib/src/aeris_api.dart
@@ -1,127 +1,249 @@
+// ignore_for_file: unused_import
+
import 'dart:async';
-import 'package:aeris/src/models/action.dart';
+import 'dart:convert';
+import 'dart:io';
+import 'package:aeris/main.dart';
+import 'package:aeris/src/models/action.dart' as aeris;
+import 'package:aeris/src/models/action_parameter.dart';
import 'package:aeris/src/models/action_template.dart';
import 'package:aeris/src/models/pipeline.dart';
import 'package:aeris/src/models/reaction.dart';
import 'package:aeris/src/models/service.dart';
import 'package:aeris/src/models/trigger.dart';
+import 'package:aeris/src/providers/action_catalogue_provider.dart';
+import 'package:flutter/material.dart';
+import 'package:get_it/get_it.dart';
+import 'package:path_provider/path_provider.dart';
+import 'package:http/http.dart' as http;
+import 'package:provider/provider.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+
+extension IsOk on http.Response {
+ bool get ok => (statusCode ~/ 100) == 2;
+}
+
+/// Requests types supported by Aeris API
+enum AerisAPIRequestType { get, post, put, delete }
/// Call to interact with Aeris' Back end
class AerisAPI {
- ///TODO set status based on stored credentials
- bool connected = true;
- late List fakeAPI;
+ /// Get Connection state
+ bool _connected = false;
+ bool get isConnected => _connected;
+
+ /// JWT token used to request API
+ late String _jwt;
+
+ late final String deepLinkRoute;
+
+ String _baseRoute =
+ GetIt.I().getString('api') ?? "http://localhost:8080";
+ String get baseRoute => _baseRoute;
+ set baseRoute(value) => _baseRoute = value;
AerisAPI() {
- var trigger1 = Trigger(
- service: const Service.spotify(),
- name: "Play song",
- last: DateTime.now());
- var trigger3 = Trigger(
- service: const Service.discord(),
- name: "Send a message",
- last: DateTime.now());
- var trigger2 = Trigger(
- service: const Service.spotify(),
- name: "Play song",
- last: DateTime.parse("2022-01-01"));
- var reaction = Reaction(
- service: const Service.twitter(), parameters: {}, name: "Post a tweet");
- var reaction2 = Reaction(
- service: const Service.gmail(), parameters: {}, name: "Do smth");
- var reaction1 = Reaction(
- service: const Service.youtube(), parameters: {}, name: "Do smth youtube");
- var pipeline1 = Pipeline(
- id: 10,
- name: "My Action",
- triggerCount: 1,
- enabled: true,
- trigger: trigger1,
- reactions: [reaction]);
- var pipeline2 = Pipeline(
- id: 10,
- name: "My very long action Action",
- triggerCount: 10,
- enabled: true,
- trigger: trigger2,
- reactions: [reaction, reaction1, reaction2]);
- var pipeline3 = Pipeline(
- id: 10,
- name: "Disabled",
- triggerCount: 3,
- enabled: false,
- trigger: trigger3,
- reactions: [reaction]);
- fakeAPI = [
- pipeline3,
- pipeline2,
- pipeline1,
- pipeline3,
- pipeline2,
- pipeline1,
- pipeline3,
- pipeline2,
- pipeline1
- ];
+ var scheme = "http";
+ if (Platform.isIOS) {
+ scheme = "aeris";
+ }
+ deepLinkRoute = "$scheme://arthichaud.me";
}
- /// Adds new pipeline to API
- Future createPipeline(Pipeline newPipeline) async {
- ///TODO Send Pipeline to API
- fakeAPI.add(newPipeline);
- await Future.delayed(const Duration(seconds: 2));
- return;
+ /// Name of the file that contains the JWT used for Aeris' API requestd
+ static const String jwtFile = 'aeris_jwt.txt';
+
+ ///ROUTES
+ /// Registers new user in the database and connects it. Returns false if register failed
+ Future signUpUser(String username, String password) async {
+ http.Response response =
+ await _requestAPI('/auth/signup', AerisAPIRequestType.post, {
+ 'username': username,
+ 'password': password,
+ });
+ if (!response.ok) {
+ return false;
+ }
+ return createConnection(username, password);
+ }
+
+ /// On success, sets API as connected to given user. Returns false if connection false
+ Future createConnection(String username, String password) async {
+ http.Response response =
+ await _requestAPI('/auth/login', AerisAPIRequestType.post, {
+ 'username': username,
+ 'password': password,
+ });
+ if (!response.ok) {
+ return false;
+ }
+ try {
+ final String jwt = jsonDecode(response.body)['jwt'];
+ await GetIt.I().setString('jwt', jwt);
+ _connected = true;
+ _jwt = jwt;
+ } catch (e) {
+ return false;
+ }
+ return true;
+ }
+
+ /// Create an API connection using previously created credentials
+ Future restoreConnection() async {
+ try {
+ final cred = GetIt.I().getString('jwt');
+ if (cred == "" || cred == null) {
+ throw Exception("Empty creds");
+ }
+ _jwt = cred;
+ _connected = true;
+ } catch (e) {
+ return;
+ }
+ }
+
+ /// Delete JWT file and disconnect from API
+ Future stopConnection() async {
+ await GetIt.I().remove('jwt');
+ _connected = false;
+ }
+
+ ///Get /about.json
+ Future