diff --git a/.DS_Store b/.DS_Store
index fbe691ba..269af6f0 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/.flutter-plugins b/.flutter-plugins
deleted file mode 100644
index 5ee678fe..00000000
--- a/.flutter-plugins
+++ /dev/null
@@ -1,6 +0,0 @@
-# This is a generated file; do not edit or check into version control.
-firebase_core=/Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core-1.12.0/
-firebase_core_web=/Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core_web-1.5.4/
-video_player=/Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/video_player-2.2.15/
-video_player_web=/Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/video_player_web-2.0.6/
-video_player_web_hls=/Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/video_player_web_hls-0.1.11+3/
diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies
deleted file mode 100644
index dcc97096..00000000
--- a/.flutter-plugins-dependencies
+++ /dev/null
@@ -1 +0,0 @@
-{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"firebase_core","path":"/Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core-1.12.0/","dependencies":[]},{"name":"video_player","path":"/Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/video_player-2.2.15/","dependencies":[]}],"android":[{"name":"firebase_core","path":"/Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core-1.12.0/","dependencies":[]},{"name":"video_player","path":"/Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/video_player-2.2.15/","dependencies":[]}],"macos":[{"name":"firebase_core","path":"/Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core-1.12.0/","dependencies":[]}],"linux":[],"windows":[],"web":[{"name":"firebase_core_web","path":"/Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core_web-1.5.4/","dependencies":[]},{"name":"video_player_web","path":"/Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/video_player_web-2.0.6/","dependencies":[]},{"name":"video_player_web_hls","path":"/Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/video_player_web_hls-0.1.11+3/","dependencies":[]}]},"dependencyGraph":[{"name":"firebase_core","dependencies":["firebase_core_web"]},{"name":"firebase_core_web","dependencies":[]},{"name":"video_player","dependencies":["video_player_web"]},{"name":"video_player_web","dependencies":[]},{"name":"video_player_web_hls","dependencies":[]}],"date_created":"2022-01-30 16:27:43.690884","version":"2.8.1"}
\ No newline at end of file
diff --git a/.github/workflows/android-build.yml b/.github/workflows/android-build.yml
new file mode 100644
index 00000000..de19edbb
--- /dev/null
+++ b/.github/workflows/android-build.yml
@@ -0,0 +1,30 @@
+name: Android Build
+
+on:
+ workflow_dispatch: # Allow manual triggering of the workflow
+
+jobs:
+ build:
+ name: Build Android APK
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - name: Set up Flutter
+ uses: subosito/flutter-action@v2
+ with:
+ flutter-version: stable
+
+ - name: Install dependencies
+ run: flutter pub get
+
+ - name: Build APK
+ run: flutter build apk --release
+
+ - name: Upload APK
+ uses: actions/upload-artifact@v3
+ with:
+ name: android-apk
+ path: build/app/outputs/flutter-apk/app-release.apk
diff --git a/.gitignore b/.gitignore
index 54f88372..ca093c16 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,14 @@
+android/private_key.pepk
+android/signing.properties
+android/app/store
+android/app/release/app-release.aab
+android/.idea/**
+android/.idea
+.env
+.flutter-plugins-dependencies
+.flutter-plugins
+
+
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
@@ -22,6 +33,8 @@ DerivedData/
*.perspectivev3
!default.perspectivev3
+ios/vendor
+
## Obj-C/Swift specific
*.hmap
@@ -89,4 +102,9 @@ fastlane/test_output
iOSInjectionProject/
-.dart_tool
\ No newline at end of file
+.dart_tool
+.env
+dotenv
+*.env
+
+.idea
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 26d33521..00000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
diff --git a/.idea/.name b/.idea/.name
deleted file mode 100644
index 1b2101d7..00000000
--- a/.idea/.name
+++ /dev/null
@@ -1 +0,0 @@
-acela
\ No newline at end of file
diff --git a/.idea/Android-App.iml b/.idea/Android-App.iml
new file mode 100644
index 00000000..d97ec2ad
--- /dev/null
+++ b/.idea/Android-App.iml
@@ -0,0 +1,210 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
deleted file mode 100644
index 4bec4ea8..00000000
--- a/.idea/codeStyles/Project.xml
+++ /dev/null
@@ -1,117 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- xmlns:android
-
- ^$
-
-
-
-
-
-
-
-
- xmlns:.*
-
- ^$
-
-
- BY_NAME
-
-
-
-
-
-
- .*:id
-
- http://schemas.android.com/apk/res/android
-
-
-
-
-
-
-
-
- .*:name
-
- http://schemas.android.com/apk/res/android
-
-
-
-
-
-
-
-
- name
-
- ^$
-
-
-
-
-
-
-
-
- style
-
- ^$
-
-
-
-
-
-
-
-
- .*
-
- ^$
-
-
- BY_NAME
-
-
-
-
-
-
- .*
-
- http://schemas.android.com/apk/res/android
-
-
- ANDROID_ATTRIBUTE_ORDER
-
-
-
-
-
-
- .*
-
- .*
-
-
- BY_NAME
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
deleted file mode 100644
index a55e7a17..00000000
--- a/.idea/codeStyles/codeStyleConfig.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml
deleted file mode 100644
index 6a2abd22..00000000
--- a/.idea/libraries/Dart_Packages.xml
+++ /dev/null
@@ -1,348 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Dart_SDK.xml b/.idea/libraries/Dart_SDK.xml
index 6cba42fc..d4bb4d42 100644
--- a/.idea/libraries/Dart_SDK.xml
+++ b/.idea/libraries/Dart_SDK.xml
@@ -1,25 +1,27 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.idea/libraries/Flutter_Plugins.xml b/.idea/libraries/Flutter_Plugins.xml
index 2d99f4f8..a35cb6dc 100644
--- a/.idea/libraries/Flutter_Plugins.xml
+++ b/.idea/libraries/Flutter_Plugins.xml
@@ -1,11 +1,74 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.idea/libraries/KotlinJavaRuntime.xml b/.idea/libraries/KotlinJavaRuntime.xml
deleted file mode 100644
index 2b96ac4b..00000000
--- a/.idea/libraries/KotlinJavaRuntime.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index f4f6d798..00000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index bc717bbb..b8bc9936 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -2,7 +2,7 @@
-
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/main_dart.xml b/.idea/runConfigurations/main_dart.xml
deleted file mode 100644
index aab7b5cd..00000000
--- a/.idea/runConfigurations/main_dart.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.metadata b/.metadata
deleted file mode 100644
index fd70cabc..00000000
--- a/.metadata
+++ /dev/null
@@ -1,10 +0,0 @@
-# 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 and should not be manually edited.
-
-version:
- revision: 77d935af4db863f6abd0b9c31c7e6df2a13de57b
- channel: stable
-
-project_type: app
diff --git a/.packages b/.packages
deleted file mode 100644
index 3dcda11b..00000000
--- a/.packages
+++ /dev/null
@@ -1,49 +0,0 @@
-# This file is deprecated. Tools should instead consume
-# `.dart_tool/package_config.json`.
-#
-# For more info see: https://dart.dev/go/dot-packages-deprecation
-#
-# Generated by pub on 2022-01-30 16:15:49.484679.
-args:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/args-2.3.0/lib/
-async:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/async-2.8.2/lib/
-boolean_selector:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0/lib/
-characters:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/characters-1.2.0/lib/
-charcode:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/charcode-1.3.1/lib/
-clock:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0/lib/
-collection:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0/lib/
-csslib:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/csslib-0.17.1/lib/
-fake_async:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0/lib/
-firebase_core:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core-1.12.0/lib/
-firebase_core_platform_interface:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core_platform_interface-4.2.4/lib/
-firebase_core_web:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core_web-1.5.4/lib/
-flutter:file:///Applications/flutter/flutter/packages/flutter/lib/
-flutter_lints:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_lints-1.0.4/lib/
-flutter_markdown:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_markdown-0.6.9/lib/
-flutter_test:file:///Applications/flutter/flutter/packages/flutter_test/lib/
-flutter_web_plugins:file:///Applications/flutter/flutter/packages/flutter_web_plugins/lib/
-html:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/html-0.15.0/lib/
-http:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/http-0.13.4/lib/
-http_parser:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/http_parser-4.0.0/lib/
-js:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/js-0.6.3/lib/
-lints:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/lints-1.0.1/lib/
-markdown:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/markdown-4.0.1/lib/
-matcher:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.11/lib/
-meta:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/meta-1.7.0/lib/
-path:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/path-1.8.0/lib/
-pedantic:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/pedantic-1.11.1/lib/
-plugin_platform_interface:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/plugin_platform_interface-2.1.2/lib/
-sky_engine:file:///Applications/flutter/flutter/bin/cache/pkg/sky_engine/lib/
-source_span:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.1/lib/
-stack_trace:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib/
-stream_channel:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0/lib/
-string_scanner:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0/lib/
-term_glyph:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0/lib/
-test_api:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/test_api-0.4.3/lib/
-timeago:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/timeago-3.1.0/lib/
-typed_data:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0/lib/
-vector_math:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.1/lib/
-video_player:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/video_player-2.2.15/lib/
-video_player_platform_interface:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/video_player_platform_interface-4.2.0/lib/
-video_player_web:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/video_player_web-2.0.6/lib/
-video_player_web_hls:file:///Applications/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/video_player_web_hls-0.1.11+3/lib/
-acela:lib/
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 00000000..ec5f3c57
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,38 @@
+FROM mingc/android-build-box:latest
+
+RUN apt-get update
+RUN apt-get install -y curl git wget unzip libgconf-2-4 gdb libstdc++6 libglu1-mesa fonts-droid-fallback lib32stdc++6 python3
+RUN apt-get clean
+
+# download Flutter SDK from Flutter Github repo
+RUN git clone https://github.com/flutter/flutter.git /usr/local/flutter
+
+# Set flutter environment path
+ENV PATH="/usr/local/flutter/bin:/usr/local/flutter/bin/cache/dart-sdk/bin:${PATH}"
+
+# Run flutter doctor
+RUN flutter doctor
+
+# Install Android SDK dependencies
+RUN apt-get update && apt-get install -y \
+ openjdk-11-jdk \
+ && apt-get clean
+
+
+
+RUN eval "$(jenv init -)"
+
+# Create and set the working directory
+WORKDIR /app
+
+# Copy the Flutter project into the container
+COPY . .
+
+# Check Flutter
+RUN flutter doctor
+
+# Get Flutter dependencies
+RUN flutter pub get
+
+# Build the Flutter project for Android
+CMD ["flutter", "build", "aab", "--release"]
diff --git a/acela.iml b/acela.iml
index dec007d1..e6299203 100644
--- a/acela.iml
+++ b/acela.iml
@@ -54,6 +54,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/analysis_options.yaml b/analysis_options.yaml
deleted file mode 100644
index 61b6c4de..00000000
--- a/analysis_options.yaml
+++ /dev/null
@@ -1,29 +0,0 @@
-# This file configures the analyzer, which statically analyzes Dart code to
-# check for errors, warnings, and lints.
-#
-# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
-# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
-# invoked from the command line by running `flutter analyze`.
-
-# The following line activates a set of recommended lints for Flutter apps,
-# packages, and plugins designed to encourage good coding practices.
-include: package:flutter_lints/flutter.yaml
-
-linter:
- # The lint rules applied to this project can be customized in the
- # section below to disable rules from the `package:flutter_lints/flutter.yaml`
- # included above or to enable additional rules. A list of all available lints
- # and their documentation is published at
- # https://dart-lang.github.io/linter/lints/index.html.
- #
- # Instead of disabling a lint rule for the entire project in the
- # section below, it can also be suppressed for a single line of code
- # or a specific dart file by using the `// ignore: name_of_lint` and
- # `// ignore_for_file: name_of_lint` syntax on the line or in the file
- # producing the lint.
- rules:
- # avoid_print: false # Uncomment to disable the `avoid_print` rule
- # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
-
-# Additional information about this file can be found at
-# https://dart.dev/guides/language/analysis-options
diff --git a/android/.gitignore b/android/.gitignore
index 6f568019..fd140eb1 100644
--- a/android/.gitignore
+++ b/android/.gitignore
@@ -11,3 +11,5 @@ GeneratedPluginRegistrant.java
key.properties
**/*.keystore
**/*.jks
+/.idea
+.idea
\ No newline at end of file
diff --git a/android/.idea/.gitignore b/android/.idea/.gitignore
deleted file mode 100644
index 26d33521..00000000
--- a/android/.idea/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
diff --git a/android/.idea/assetWizardSettings.xml b/android/.idea/assetWizardSettings.xml
deleted file mode 100644
index ba5438e8..00000000
--- a/android/.idea/assetWizardSettings.xml
+++ /dev/null
@@ -1,292 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/compiler.xml b/android/.idea/compiler.xml
deleted file mode 100644
index fb7f4a8a..00000000
--- a/android/.idea/compiler.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/gradle.xml b/android/.idea/gradle.xml
index 1c4cf4dc..bb7ef750 100644
--- a/android/.idea/gradle.xml
+++ b/android/.idea/gradle.xml
@@ -4,17 +4,57 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/android/.idea/jarRepositories.xml b/android/.idea/jarRepositories.xml
deleted file mode 100644
index 75fe4bc9..00000000
--- a/android/.idea/jarRepositories.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle_______build_app_intermediates_flutter_debug_libs_jar.xml b/android/.idea/libraries/Gradle_______build_app_intermediates_flutter_debug_libs_jar.xml
deleted file mode 100644
index 106c5b36..00000000
--- a/android/.idea/libraries/Gradle_______build_app_intermediates_flutter_debug_libs_jar.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml b/android/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
deleted file mode 100644
index 06d1f863..00000000
--- a/android/.idea/libraries/Gradle__androidx_activity_activity_1_0_0_aar.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_annotation_annotation_1_2_0.xml b/android/.idea/libraries/Gradle__androidx_annotation_annotation_1_2_0.xml
deleted file mode 100644
index 74437d76..00000000
--- a/android/.idea/libraries/Gradle__androidx_annotation_annotation_1_2_0.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_1_0_aar.xml b/android/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_1_0_aar.xml
deleted file mode 100644
index 69540c2d..00000000
--- a/android/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_1_0_aar.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml b/android/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
deleted file mode 100644
index 22084152..00000000
--- a/android/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml b/android/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
deleted file mode 100644
index 28098333..00000000
--- a/android/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_0_0_aar.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml b/android/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
deleted file mode 100644
index eafc05e9..00000000
--- a/android/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_core_core_1_6_0_aar.xml b/android/.idea/libraries/Gradle__androidx_core_core_1_6_0_aar.xml
deleted file mode 100644
index f171ace3..00000000
--- a/android/.idea/libraries/Gradle__androidx_core_core_1_6_0_aar.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml b/android/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
deleted file mode 100644
index cbcb46a4..00000000
--- a/android/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml b/android/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
deleted file mode 100644
index c1e43822..00000000
--- a/android/.idea/libraries/Gradle__androidx_fragment_fragment_1_1_0_aar.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml b/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
deleted file mode 100644
index f7d64790..00000000
--- a/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_2_0.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_java8_2_2_0.xml b/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_java8_2_2_0.xml
deleted file mode 100644
index fc8d6778..00000000
--- a/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_java8_2_2_0.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml b/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
deleted file mode 100644
index 15e56ddf..00000000
--- a/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml b/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
deleted file mode 100644
index 73bb1d5e..00000000
--- a/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_0_0_aar.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml b/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
deleted file mode 100644
index a05f2022..00000000
--- a/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_2_0_aar.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml b/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
deleted file mode 100644
index bcfcd11e..00000000
--- a/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_1_0_aar.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml b/android/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
deleted file mode 100644
index 2f72bddb..00000000
--- a/android/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml b/android/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
deleted file mode 100644
index 811dc169..00000000
--- a/android/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_0_0_aar.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_tracing_tracing_1_0_0_aar.xml b/android/.idea/libraries/Gradle__androidx_tracing_tracing_1_0_0_aar.xml
deleted file mode 100644
index aa35bb79..00000000
--- a/android/.idea/libraries/Gradle__androidx_tracing_tracing_1_0_0_aar.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_1_aar.xml b/android/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_1_aar.xml
deleted file mode 100644
index 611a088b..00000000
--- a/android/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_1_aar.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml b/android/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
deleted file mode 100644
index 4f214927..00000000
--- a/android/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__com_google_android_exoplayer_exoplayer_common_2_14_1_aar.xml b/android/.idea/libraries/Gradle__com_google_android_exoplayer_exoplayer_common_2_14_1_aar.xml
deleted file mode 100644
index 9062fc06..00000000
--- a/android/.idea/libraries/Gradle__com_google_android_exoplayer_exoplayer_common_2_14_1_aar.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__com_google_android_exoplayer_exoplayer_core_2_14_1_aar.xml b/android/.idea/libraries/Gradle__com_google_android_exoplayer_exoplayer_core_2_14_1_aar.xml
deleted file mode 100644
index 5b786594..00000000
--- a/android/.idea/libraries/Gradle__com_google_android_exoplayer_exoplayer_core_2_14_1_aar.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__com_google_android_exoplayer_exoplayer_dash_2_14_1_aar.xml b/android/.idea/libraries/Gradle__com_google_android_exoplayer_exoplayer_dash_2_14_1_aar.xml
deleted file mode 100644
index 4d305f4d..00000000
--- a/android/.idea/libraries/Gradle__com_google_android_exoplayer_exoplayer_dash_2_14_1_aar.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__com_google_android_exoplayer_exoplayer_extractor_2_14_1_aar.xml b/android/.idea/libraries/Gradle__com_google_android_exoplayer_exoplayer_extractor_2_14_1_aar.xml
deleted file mode 100644
index dc32ca16..00000000
--- a/android/.idea/libraries/Gradle__com_google_android_exoplayer_exoplayer_extractor_2_14_1_aar.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__com_google_android_exoplayer_exoplayer_hls_2_14_1_aar.xml b/android/.idea/libraries/Gradle__com_google_android_exoplayer_exoplayer_hls_2_14_1_aar.xml
deleted file mode 100644
index b7002dbf..00000000
--- a/android/.idea/libraries/Gradle__com_google_android_exoplayer_exoplayer_hls_2_14_1_aar.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__com_google_android_exoplayer_exoplayer_smoothstreaming_2_14_1_aar.xml b/android/.idea/libraries/Gradle__com_google_android_exoplayer_exoplayer_smoothstreaming_2_14_1_aar.xml
deleted file mode 100644
index 3a95a7fa..00000000
--- a/android/.idea/libraries/Gradle__com_google_android_exoplayer_exoplayer_smoothstreaming_2_14_1_aar.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml b/android/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
deleted file mode 100644
index aeb2fc76..00000000
--- a/android/.idea/libraries/Gradle__com_google_guava_failureaccess_1_0_1.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__com_google_guava_guava_27_1_android.xml b/android/.idea/libraries/Gradle__com_google_guava_guava_27_1_android.xml
deleted file mode 100644
index 62babcfd..00000000
--- a/android/.idea/libraries/Gradle__com_google_guava_guava_27_1_android.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml b/android/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
deleted file mode 100644
index 11f8cce0..00000000
--- a/android/.idea/libraries/Gradle__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__io_flutter_arm64_v8a_debug_1_0_0_890a5fca2e34db413be624fc83aeea8e61d42ce6.xml b/android/.idea/libraries/Gradle__io_flutter_arm64_v8a_debug_1_0_0_890a5fca2e34db413be624fc83aeea8e61d42ce6.xml
deleted file mode 100644
index f8a806a2..00000000
--- a/android/.idea/libraries/Gradle__io_flutter_arm64_v8a_debug_1_0_0_890a5fca2e34db413be624fc83aeea8e61d42ce6.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__io_flutter_armeabi_v7a_debug_1_0_0_890a5fca2e34db413be624fc83aeea8e61d42ce6.xml b/android/.idea/libraries/Gradle__io_flutter_armeabi_v7a_debug_1_0_0_890a5fca2e34db413be624fc83aeea8e61d42ce6.xml
deleted file mode 100644
index 067ef82c..00000000
--- a/android/.idea/libraries/Gradle__io_flutter_armeabi_v7a_debug_1_0_0_890a5fca2e34db413be624fc83aeea8e61d42ce6.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__io_flutter_flutter_embedding_debug_1_0_0_890a5fca2e34db413be624fc83aeea8e61d42ce6.xml b/android/.idea/libraries/Gradle__io_flutter_flutter_embedding_debug_1_0_0_890a5fca2e34db413be624fc83aeea8e61d42ce6.xml
deleted file mode 100644
index f7ecc2e8..00000000
--- a/android/.idea/libraries/Gradle__io_flutter_flutter_embedding_debug_1_0_0_890a5fca2e34db413be624fc83aeea8e61d42ce6.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__io_flutter_x86_64_debug_1_0_0_890a5fca2e34db413be624fc83aeea8e61d42ce6.xml b/android/.idea/libraries/Gradle__io_flutter_x86_64_debug_1_0_0_890a5fca2e34db413be624fc83aeea8e61d42ce6.xml
deleted file mode 100644
index 5b11ae43..00000000
--- a/android/.idea/libraries/Gradle__io_flutter_x86_64_debug_1_0_0_890a5fca2e34db413be624fc83aeea8e61d42ce6.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__io_flutter_x86_debug_1_0_0_890a5fca2e34db413be624fc83aeea8e61d42ce6.xml b/android/.idea/libraries/Gradle__io_flutter_x86_debug_1_0_0_890a5fca2e34db413be624fc83aeea8e61d42ce6.xml
deleted file mode 100644
index 2b9a9dfc..00000000
--- a/android/.idea/libraries/Gradle__io_flutter_x86_debug_1_0_0_890a5fca2e34db413be624fc83aeea8e61d42ce6.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__junit_junit_4_12.xml b/android/.idea/libraries/Gradle__junit_junit_4_12.xml
deleted file mode 100644
index 6c078d62..00000000
--- a/android/.idea/libraries/Gradle__junit_junit_4_12.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__net_bytebuddy_byte_buddy_1_10_20.xml b/android/.idea/libraries/Gradle__net_bytebuddy_byte_buddy_1_10_20.xml
deleted file mode 100644
index 3a6cfb29..00000000
--- a/android/.idea/libraries/Gradle__net_bytebuddy_byte_buddy_1_10_20.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__net_bytebuddy_byte_buddy_agent_1_10_20.xml b/android/.idea/libraries/Gradle__net_bytebuddy_byte_buddy_agent_1_10_20.xml
deleted file mode 100644
index ccb3d374..00000000
--- a/android/.idea/libraries/Gradle__net_bytebuddy_byte_buddy_agent_1_10_20.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__org_hamcrest_hamcrest_core_1_3.xml b/android/.idea/libraries/Gradle__org_hamcrest_hamcrest_core_1_3.xml
deleted file mode 100644
index 09cf23d1..00000000
--- a/android/.idea/libraries/Gradle__org_hamcrest_hamcrest_core_1_3.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml b/android/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
deleted file mode 100644
index 1fa0fa9f..00000000
--- a/android/.idea/libraries/Gradle__org_jetbrains_annotations_13_0.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_3_50.xml b/android/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_3_50.xml
deleted file mode 100644
index e03b2f64..00000000
--- a/android/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_3_50.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_3_50.xml b/android/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_3_50.xml
deleted file mode 100644
index 861597d5..00000000
--- a/android/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_3_50.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_3_50.xml b/android/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_3_50.xml
deleted file mode 100644
index 8dfcb211..00000000
--- a/android/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jdk7_1_3_50.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__org_mockito_mockito_core_3_9_0.xml b/android/.idea/libraries/Gradle__org_mockito_mockito_core_3_9_0.xml
deleted file mode 100644
index 31d2f832..00000000
--- a/android/.idea/libraries/Gradle__org_mockito_mockito_core_3_9_0.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__org_mockito_mockito_inline_3_9_0.xml b/android/.idea/libraries/Gradle__org_mockito_mockito_inline_3_9_0.xml
deleted file mode 100644
index 448d71fc..00000000
--- a/android/.idea/libraries/Gradle__org_mockito_mockito_inline_3_9_0.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/libraries/Gradle__org_objenesis_objenesis_3_2.xml b/android/.idea/libraries/Gradle__org_objenesis_objenesis_3_2.xml
deleted file mode 100644
index 755fe5c6..00000000
--- a/android/.idea/libraries/Gradle__org_objenesis_objenesis_3_2.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/misc.xml b/android/.idea/misc.xml
index 2a4d5b52..8978d23d 100644
--- a/android/.idea/misc.xml
+++ b/android/.idea/misc.xml
@@ -1,6 +1,6 @@
-
-
+
+
diff --git a/android/.idea/modules.xml b/android/.idea/modules.xml
deleted file mode 100644
index d647f933..00000000
--- a/android/.idea/modules.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/modules/-1065946935/android.video_player.iml b/android/.idea/modules/-1065946935/android.video_player.iml
deleted file mode 100644
index 6a5712d2..00000000
--- a/android/.idea/modules/-1065946935/android.video_player.iml
+++ /dev/null
@@ -1,97 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- generateDebugSources
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/modules/android.iml b/android/.idea/modules/android.iml
deleted file mode 100644
index 4e86d157..00000000
--- a/android/.idea/modules/android.iml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/.idea/modules/app/android.app.iml b/android/.idea/modules/app/android.app.iml
deleted file mode 100644
index 5d0b5c76..00000000
--- a/android/.idea/modules/app/android.app.iml
+++ /dev/null
@@ -1,116 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- generateDebugSources
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/acela_android.iml b/android/acela_android.iml
index 18999696..3e44773e 100644
--- a/android/acela_android.iml
+++ b/android/acela_android.iml
@@ -26,4 +26,4 @@
-
+
\ No newline at end of file
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 0500500d..45aa690c 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -1,3 +1,9 @@
+plugins {
+ id "com.android.application"
+ id "kotlin-android"
+ id "dev.flutter.flutter-gradle-plugin"
+}
+
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
@@ -6,11 +12,6 @@ if (localPropertiesFile.exists()) {
}
}
-def flutterRoot = localProperties.getProperty('flutter.sdk')
-if (flutterRoot == null) {
- throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
-}
-
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
@@ -21,13 +22,16 @@ if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
-apply plugin: 'com.google.gms.google-services'
-apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+def keystoreProperties = new Properties()
+def keystorePropertiesFile = rootProject.file('signing.properties')
+if (keystorePropertiesFile.exists()) {
+ keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
+}
android {
- compileSdkVersion flutter.compileSdkVersion
+ ndkVersion "23.1.7779620"
+ compileSdkVersion 34
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
@@ -43,28 +47,52 @@ android {
}
defaultConfig {
- // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
- applicationId "com.example.acela"
- minSdkVersion flutter.minSdkVersion
- targetSdkVersion flutter.targetSdkVersion
+ applicationId "tv.threespeak.app"
+ minSdkVersion 24
+ targetSdkVersion 34
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
+ multiDexEnabled true
+ }
+
+ signingConfigs {
+ release {
+ keyAlias keystoreProperties['keyAlias']
+ keyPassword keystoreProperties['keyPassword']
+ storeFile keystoreProperties['storeFilePath'] ? file(keystoreProperties['storeFilePath']) : null
+ storePassword keystoreProperties['storePassword']
+ }
}
buildTypes {
release {
- // TODO: Add your own signing config for the release build.
- // Signing with the debug keys for now, so `flutter run --release` works.
- signingConfig signingConfigs.debug
+ minifyEnabled false
+ shrinkResources false
+ // signingConfig signingConfigs.release
}
}
+ buildFeatures {
+ viewBinding true
+ }
+ namespace 'tv.threespeak.app'
}
flutter {
source '../..'
}
+def mediaVersion = "1.0.2"
+
dependencies {
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
- implementation platform('com.google.firebase:firebase-bom:29.0.4')
+ implementation 'androidx.webkit:webkit:1.6.1'
+ implementation 'com.google.code.gson:gson:2.9.0'
+ implementation 'androidx.appcompat:appcompat:1.6.1'
+ implementation 'com.google.android.material:material:1.4.+'
+
+ implementation 'com.google.android.exoplayer:exoplayer:2.18.7'
+
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+ implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3'
+ implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
+ implementation "androidx.multidex:multidex:2.0.1"
}
diff --git a/android/app/google-services.json b/android/app/google-services.json
index 0ef1234b..5bc6a5a7 100644
--- a/android/app/google-services.json
+++ b/android/app/google-services.json
@@ -7,9 +7,9 @@
"client": [
{
"client_info": {
- "mobilesdk_app_id": "1:252548198943:android:ea163470c7c668c9355b2a",
+ "mobilesdk_app_id": "1:252548198943:android:3af79775d4815fab355b2a",
"android_client_info": {
- "package_name": "com.example.acela"
+ "package_name": "tv.threespeak.app"
}
},
"oauth_client": [
@@ -29,6 +29,13 @@
{
"client_id": "252548198943-gu14ujl4f9b45042d76b4tq6h8n1aa4a.apps.googleusercontent.com",
"client_type": 3
+ },
+ {
+ "client_id": "252548198943-ec3gnethnkvoudaat0lrobmq2t7mve8g.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.example.acela"
+ }
}
]
}
diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml
index 0820d81a..f880684a 100644
--- a/android/app/src/debug/AndroidManifest.xml
+++ b/android/app/src/debug/AndroidManifest.xml
@@ -1,5 +1,4 @@
-
+
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index ca3fe0cc..d2096b0f 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -1,35 +1,92 @@
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+ android:icon="@mipmap/ic_launcher"
+ android:label="3Speak"
+ android:usesCleartextTraffic="true"
+ android:requestLegacyExternalStorage="true"
+ >
+
+
+
+
+
-
+ to determine the Window background behind the Flutter UI.
+
+ android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
+ -->
+ android:name="io.flutter.embedding.android.NormalTheme"
+ android:resource="@style/NormalTheme" />
+
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
\ No newline at end of file
diff --git a/android/app/src/main/assets/index.html b/android/app/src/main/assets/index.html
new file mode 100644
index 00000000..0f716c74
--- /dev/null
+++ b/android/app/src/main/assets/index.html
@@ -0,0 +1,921 @@
+
+
+
+
+
+
+
+ 3Speak
+
+
+
+ You need to enable JavaScript to run this app.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/java/tv/threespeak/app/MediaPlayerService.kt b/android/app/src/main/java/tv/threespeak/app/MediaPlayerService.kt
new file mode 100644
index 00000000..08e75ee0
--- /dev/null
+++ b/android/app/src/main/java/tv/threespeak/app/MediaPlayerService.kt
@@ -0,0 +1,58 @@
+package tv.threespeak.app
+
+import android.app.Service
+import android.content.Intent
+import android.media.AudioManager
+import android.media.MediaPlayer
+import android.os.Binder
+import android.os.IBinder
+
+
+class MediaPlayerService : Service(), MediaPlayer.OnCompletionListener,
+ MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener,
+ MediaPlayer.OnSeekCompleteListener, MediaPlayer.OnInfoListener,
+ MediaPlayer.OnBufferingUpdateListener, AudioManager.OnAudioFocusChangeListener {
+ // Binder given to clients
+ private val iBinder: IBinder = LocalBinder()
+
+ override fun onBind(intent: Intent?): IBinder {
+ return iBinder
+ }
+
+ override fun onBufferingUpdate(mp: MediaPlayer, percent: Int) {
+ //Invoked indicating buffering status of
+ //a media resource being streamed over the network.
+ }
+
+ override fun onCompletion(mp: MediaPlayer) {
+ //Invoked when playback of a media source has completed.
+ }
+
+ //Handle errors
+ override fun onError(mp: MediaPlayer, what: Int, extra: Int): Boolean {
+ //Invoked when there has been an error during an asynchronous operation.
+ return false
+ }
+
+ override fun onInfo(mp: MediaPlayer, what: Int, extra: Int): Boolean {
+ //Invoked to communicate some info.
+ return false
+ }
+
+ override fun onPrepared(mp: MediaPlayer) {
+ //Invoked when the media source is ready for playback.
+ }
+
+ override fun onSeekComplete(mp: MediaPlayer) {
+ //Invoked indicating the completion of a seek operation.
+ }
+
+ override fun onAudioFocusChange(focusChange: Int) {
+ //Invoked when the audio focus of the system is updated.
+ }
+
+ inner class LocalBinder : Binder() {
+ val service: MediaPlayerService
+ get() = this@MediaPlayerService
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/java/tv/threespeak/app/VideoPlayerActivity.kt b/android/app/src/main/java/tv/threespeak/app/VideoPlayerActivity.kt
new file mode 100644
index 00000000..67bd2c9c
--- /dev/null
+++ b/android/app/src/main/java/tv/threespeak/app/VideoPlayerActivity.kt
@@ -0,0 +1,103 @@
+package tv.threespeak.app
+
+import android.media.AudioManager
+import android.media.MediaPlayer
+import android.net.Uri
+import android.os.Bundle
+import android.os.PersistableBundle
+import androidx.appcompat.app.AppCompatActivity
+import com.google.android.exoplayer2.ExoPlayer
+import com.google.android.exoplayer2.MediaItem
+import com.google.android.exoplayer2.util.MimeTypes
+import tv.threespeak.app.databinding.ActivityVideoPlayerBinding
+import java.io.IOException
+
+
+/**
+ * An example full-screen activity that shows and hides the system UI (i.e.
+ * status bar and navigation/system bar) with user interaction.
+ */
+class VideoPlayerActivity : AppCompatActivity() {
+ private lateinit var binding: ActivityVideoPlayerBinding
+ private var seconds = 0
+ private var url = "https://ipfs-3speak.b-cdn.net/ipfs/QmYS9k6LTkbix77XPitT5sGqLKmzfQ9h2qg1ucSwwTFSxx/480p/index.m3u8"
+
+ override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
+ super.onCreate(savedInstanceState, persistentState)
+ initializePlayer()
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityVideoPlayerBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ intent.extras?.getInt("seconds")?.let {
+ this.seconds = it
+ }
+ intent.extras?.getString("url")?.let {
+ this.url = it
+ }
+
+ // to go complete full screen
+// WindowCompat.setDecorFitsSystemWindows(window, false)
+// WindowInsetsControllerCompat(window, binding.videoView).let { controller ->
+// controller.hide(WindowInsetsCompat.Type.systemBars())
+// controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+// }
+ }
+
+ private var mediaPlayer: MediaPlayer? = null
+
+ private fun initMediaPlayer() {
+ mediaPlayer = MediaPlayer()
+ mediaPlayer!!.setOnPreparedListener {
+ it.start()
+ }
+ mediaPlayer!!.reset()
+ // mediaPlayer!!.setAudioStreamType(AudioManager.STREAM_MUSIC)
+ try {
+ // Set the data source to the mediaFile location
+ mediaPlayer!!.setDataSource(this, Uri.parse(url))
+ } catch (e: IOException) {
+ e.printStackTrace()
+ // stopSelf()
+ }
+ mediaPlayer!!.prepareAsync()
+ }
+
+ private fun initializePlayer() {
+ binding.videoView.player = ExoPlayer.Builder(this)
+ .build()
+ .also { exoPlayer ->
+
+ val mediaItem = MediaItem
+ .Builder()
+ .setUri(url)
+ .setMimeType(MimeTypes.APPLICATION_M3U8)
+ .build()
+
+ exoPlayer.setMediaItem(mediaItem)
+ exoPlayer.seekTo((1000 * seconds).toLong())
+ exoPlayer.playWhenReady = true
+ exoPlayer.prepare()
+ }
+ }
+
+ public override fun onStart() {
+ super.onStart()
+ initializePlayer()
+// initMediaPlayer()
+ }
+
+ public override fun onStop() {
+ super.onStop()
+ releasePlayer()
+ }
+
+ private fun releasePlayer() {
+ binding.videoView.player?.let { exoPlayer ->
+ exoPlayer.release()
+ }
+ binding.videoView.player = null
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/example/acela/MainActivity.kt b/android/app/src/main/kotlin/com/example/acela/MainActivity.kt
deleted file mode 100644
index 61f7ab10..00000000
--- a/android/app/src/main/kotlin/com/example/acela/MainActivity.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.example.acela
-
-import io.flutter.embedding.android.FlutterActivity
-
-class MainActivity: FlutterActivity() {
-}
diff --git a/android/app/src/main/kotlin/tv/threespeak/app/MainActivity.kt b/android/app/src/main/kotlin/tv/threespeak/app/MainActivity.kt
new file mode 100644
index 00000000..ce41f81e
--- /dev/null
+++ b/android/app/src/main/kotlin/tv/threespeak/app/MainActivity.kt
@@ -0,0 +1,266 @@
+package tv.threespeak.app
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.Bundle
+import android.view.View
+import android.webkit.JavascriptInterface
+import android.webkit.WebResourceRequest
+import android.webkit.WebResourceResponse
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import android.widget.FrameLayout
+import androidx.annotation.NonNull
+import androidx.annotation.RequiresApi
+import androidx.webkit.WebViewAssetLoader
+import com.google.gson.Gson
+import io.flutter.embedding.android.FlutterActivity
+import io.flutter.embedding.engine.FlutterEngine
+import io.flutter.plugin.common.MethodChannel
+import com.ryanheise.audioservice.AudioServiceActivity;
+
+
+class MainActivity : AudioServiceActivity() {
+ var webView: WebView? = null
+ var result: MethodChannel.Result? = null
+
+ override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
+ super.configureFlutterEngine(flutterEngine)
+ if (webView == null) {
+ setupView()
+ }
+ MethodChannel(
+ flutterEngine.dartExecutor.binaryMessenger, "blog.hive.auth/bridge"
+ ).setMethodCallHandler { call, result ->
+ this.result = result
+ val username = call.argument("username")
+ val authKey = call.argument("authKey")
+ val data = call.argument("data")
+ if (call.method == "getRedirectUriData" && username != null) {
+ webView?.evaluateJavascript("getRedirectUriData('$username');", null)
+ } else if (call.method == "getDecryptedHASToken" && username != null && authKey != null && data != null) {
+ webView?.evaluateJavascript("getDecryptedHASToken('$username','$authKey','$data');", null)
+ } else if (call.method == "getEncryptedChallenge" && username != null && authKey != null) {
+ webView?.evaluateJavascript("getEncryptedChallenge('$username','$authKey');", null)
+ } else if (call.method == "getDecryptedChallenge" && username != null && authKey != null && data != null) {
+ webView?.evaluateJavascript("getDecryptedChallenge('$username','$authKey', '$data');", null)
+ } else if (call.method == "doWeHavePostingAuth" && username != null) {
+ webView?.evaluateJavascript("doWeHavePostingAuth('$username');", null)
+ }
+ }
+ MethodChannel(
+ flutterEngine.dartExecutor.binaryMessenger,
+ "com.example.acela/auth"
+ ).setMethodCallHandler { call, result ->
+ this.result = result
+ val username = call.argument("username")
+ val postingKey = call.argument("postingKey")
+ val params = call.argument("params")
+ val encryptedToken = call.argument("encryptedToken")
+
+ val thumbnail = call.argument("thumbnail")
+ val video_v2 = call.argument("video_v2")
+ val description = call.argument("description")
+ val title = call.argument("title")
+ val tags = call.argument("tags")
+ val permlink = call.argument("permlink")
+ val duration = call.argument("duration")
+ val size = call.argument("size")
+ val originalFilename = call.argument("originalFilename")
+ val firstUpload = call.argument("firstUpload")
+ val bene = call.argument("bene")
+ val beneW = call.argument("beneW")
+ val community = call.argument("community")
+ val ipfsHash = call.argument("ipfsHash")
+ val hasKey = call.argument("hasKey")
+ val hasAuthkey =
+ call.argument("hasAuthkey") ?: call.argument("hasAuthKey")
+ val user = call.argument("user")
+ val author = call.argument("author")
+ val weight = call.argument("weight")
+ val comment = call.argument("comment")
+ val seconds = call.argument("seconds")
+ val url = call.argument("url")
+ val newBene = call.argument("newBene")
+ val language = call.argument("language")
+ val powerUp = call.argument("powerUp")
+ val enclosureUrl = call.argument("enclosureUrl")
+ val string = call.argument("string")
+ val proof = call.argument("proof")
+
+ val data = call.argument("data")
+ if (call.method == "playFullscreen" && url != null && seconds != null) {
+ val intent = Intent(this, VideoPlayerActivity::class.java)
+ val bundle = Bundle()
+ bundle.putString("url", url)
+ bundle.putInt("seconds", seconds)
+ intent.putExtras(bundle);
+ startActivity(intent)
+ } else if (call.method == "validateHiveKey" && username != null && postingKey != null) {
+ webView?.evaluateJavascript("validateHiveKey('$username','$postingKey');", null)
+ } else if (call.method == "getProofOfPayload" && username != null && postingKey != null && proof != null) {
+ webView?.evaluateJavascript("getProofOfPayload('$username','$postingKey','$proof');", null)
+ } else if (call.method == "getHTMLStringForContent" && string != null) {
+ webView?.evaluateJavascript("getHTMLStringForContent('$string');", null)
+ } else if (call.method == "encryptedToken" && username != null
+ && postingKey != null && encryptedToken != null
+ ) {
+ webView?.evaluateJavascript(
+ "decryptMemo('$username','$postingKey', '$encryptedToken');",
+ null
+ )
+ } else if (call.method == "postVideo" && data != null && postingKey != null) {
+ webView?.evaluateJavascript("postVideo('$data','$postingKey');", null)
+ } else if (call.method == "newPostVideo" && thumbnail != null && video_v2 != null
+ && description != null && title != null && tags != null && username != null
+ && permlink != null && duration != null && size != null && originalFilename != null
+ && firstUpload != null && bene != null && beneW != null && community != null
+ && ipfsHash != null && newBene != null && language != null && powerUp != null
+ ) {
+ webView?.evaluateJavascript(
+ "newPostVideo('$thumbnail','$video_v2', '$description', '$title', '$tags', '$username', '$permlink', $duration, $size, '$originalFilename', '$language', $firstUpload, '$bene', '$beneW', '$postingKey', '$community', '$ipfsHash', '$hasKey', '$hasAuthkey', '$newBene', $powerUp);",
+ null
+ )
+ }
+ else if (call.method == "newPostPodcast" && thumbnail != null && enclosureUrl != null
+ && description != null && title != null && tags != null && username != null
+ && permlink != null && duration != null && size != null && originalFilename != null
+ && firstUpload != null && bene != null && beneW != null && community != null
+ && ipfsHash != null && newBene != null && language != null && powerUp != null
+ ) {
+ webView?.evaluateJavascript(
+ "newPostPodcast('$thumbnail','$enclosureUrl', '$description', '$title', '$tags', '$username', '$permlink', $duration, $size, '$originalFilename', '$language', $firstUpload, '$bene', '$beneW', '$postingKey', '$community', '$ipfsHash', '$hasKey', '$hasAuthkey', '$newBene', $powerUp);",
+ null
+ )
+ }
+ else if (call.method == "voteContent" && user != null && author != null
+ && permlink != null && weight != null && postingKey != null && hasKey != null
+ && hasAuthkey != null
+ ) {
+ webView?.evaluateJavascript("voteContent('$user', '$author', '$permlink', $weight, '$postingKey', '$hasKey', '$hasAuthkey');", null)
+ } else if (call.method == "commentOnContent" && user != null && author != null
+ && permlink != null && comment != null && postingKey != null && hasKey != null
+ && hasAuthkey != null
+ ) {
+ webView?.evaluateJavascript("commentOnContent('$user', '$author', '$permlink', '$comment', '$postingKey', '$hasKey', '$hasAuthkey');", null)
+ } else if (call.method == "getAccountInfo" && username != null ) {
+ webView?.evaluateJavascript(
+ "getAccountInfo('$username');",
+ null
+ )
+ }
+ }
+ }
+
+ @SuppressLint("SetJavaScriptEnabled")
+ private fun setupView() {
+ val params = FrameLayout.LayoutParams(0, 0)
+ webView = WebView(activity)
+ val decorView = activity.window.decorView as FrameLayout
+ decorView.addView(webView, params)
+ webView?.visibility = View.GONE
+ webView?.settings?.javaScriptEnabled = true
+ webView?.settings?.domStorageEnabled = true
+// webView?.webChromeClient = WebChromeClient()
+ WebView.setWebContentsDebuggingEnabled(true)
+ val assetLoader = WebViewAssetLoader.Builder()
+ .addPathHandler("/assets/", WebViewAssetLoader.AssetsPathHandler(this))
+ .build()
+ val client: WebViewClient = object : WebViewClient() {
+ @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
+ override fun shouldInterceptRequest(
+ view: WebView,
+ request: WebResourceRequest
+ ): WebResourceResponse? {
+ return assetLoader.shouldInterceptRequest(request.url)
+ }
+
+ override fun shouldInterceptRequest(
+ view: WebView,
+ url: String
+ ): WebResourceResponse? {
+ return assetLoader.shouldInterceptRequest(Uri.parse(url))
+ }
+ }
+ webView?.webViewClient = client
+ webView?.addJavascriptInterface(WebAppInterface(this), "Android")
+ webView?.loadUrl("https://appassets.androidplatform.net/assets/index.html")
+ }
+}
+
+class WebAppInterface(private val mContext: Context) {
+ @JavascriptInterface
+ fun postMessage(message: String) {
+ val main = mContext as? MainActivity ?: return
+ val gson = Gson()
+ val dataObject = gson.fromJson(message, JSEvent::class.java)
+ when (dataObject.type) {
+ JSBridgeAction.VALIDATE_HIVE_KEY.value -> {
+ main.result?.success(message)
+ }
+ JSBridgeAction.GET_REDIRECT_URI_DATA.value -> {
+ main.result?.success(message)
+ }
+ JSBridgeAction.DECRYPTED_MEMO.value -> {
+ main.result?.success(message)
+ }
+ JSBridgeAction.GET_DECRYPTED_HAS_TOKEN.value -> {
+ main.result?.success(message)
+ }
+ JSBridgeAction.POST_VIDEO.value -> {
+ main.result?.success(message)
+ }
+ JSBridgeAction.COMMENT_ON_CONTENT.value -> {
+ main.result?.success(message)
+ }
+ JSBridgeAction.VOTE_CONTENT.value -> {
+ main.result?.success(message)
+ }
+ JSBridgeAction.GET_HTML.value -> {
+ main.result?.success(message)
+ }
+ JSBridgeAction.POST_AUDIO.value -> {
+ main.result?.success(message)
+ }
+ JSBridgeAction.GET_PROOF_PAYLOAD.value -> {
+ main.result?.success(message)
+ }
+ JSBridgeAction.GET_ENCRYPTED_CHALLENGE.value -> {
+ main.result?.success(message)
+ }
+ JSBridgeAction.GET_DECRYPTED_CHALLENGE.value -> {
+ main.result?.success(message)
+ }
+ JSBridgeAction.DO_WE_HAVE_POSTING_AUTH.value -> {
+ main.result?.success(message)
+ }
+ JSBridgeAction.GET_ACCOUNT_INFO.value -> {
+ main.result?.success(message)
+ }
+ }
+ }
+}
+
+data class JSEvent(
+ val type: String,
+)
+
+enum class JSBridgeAction(val value: String) {
+ VALIDATE_HIVE_KEY("validateHiveKey"),
+ DECRYPTED_MEMO("decryptedMemo"),
+ POST_VIDEO("postVideo"),
+ GET_REDIRECT_URI_DATA("getRedirectUriData"),
+ GET_DECRYPTED_HAS_TOKEN("getDecryptedHASToken"),
+ COMMENT_ON_CONTENT("commentOnContent"),
+ VOTE_CONTENT("voteContent"),
+ GET_HTML("getHTMLStringForContent"),
+ POST_AUDIO("postAudio"),
+ GET_PROOF_PAYLOAD("getProofOfPayload"),
+ GET_ENCRYPTED_CHALLENGE("getEncryptedChallenge"),
+ GET_DECRYPTED_CHALLENGE("getDecryptedChallenge"),
+ DO_WE_HAVE_POSTING_AUTH("doWeHavePostingAuth"),
+ GET_ACCOUNT_INFO("getAccountInfo"),
+}
diff --git a/android/app/src/main/res/layout/activity_video_player.xml b/android/app/src/main/res/layout/activity_video_player.xml
new file mode 100644
index 00000000..53c8f1d3
--- /dev/null
+++ b/android/app/src/main/res/layout/activity_video_player.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/navigation/nav_graph.xml b/android/app/src/main/res/navigation/nav_graph.xml
new file mode 100644
index 00000000..a5346788
--- /dev/null
+++ b/android/app/src/main/res/navigation/nav_graph.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/values-land/dimens.xml b/android/app/src/main/res/values-land/dimens.xml
new file mode 100644
index 00000000..22d7f004
--- /dev/null
+++ b/android/app/src/main/res/values-land/dimens.xml
@@ -0,0 +1,3 @@
+
+ 48dp
+
\ No newline at end of file
diff --git a/android/app/src/main/res/values-night/themes.xml b/android/app/src/main/res/values-night/themes.xml
new file mode 100644
index 00000000..d46cc9f2
--- /dev/null
+++ b/android/app/src/main/res/values-night/themes.xml
@@ -0,0 +1,7 @@
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/values-w1240dp/dimens.xml b/android/app/src/main/res/values-w1240dp/dimens.xml
new file mode 100644
index 00000000..d73f4a35
--- /dev/null
+++ b/android/app/src/main/res/values-w1240dp/dimens.xml
@@ -0,0 +1,3 @@
+
+ 200dp
+
\ No newline at end of file
diff --git a/android/app/src/main/res/values-w600dp/dimens.xml b/android/app/src/main/res/values-w600dp/dimens.xml
new file mode 100644
index 00000000..22d7f004
--- /dev/null
+++ b/android/app/src/main/res/values-w600dp/dimens.xml
@@ -0,0 +1,3 @@
+
+ 48dp
+
\ No newline at end of file
diff --git a/android/app/src/main/res/values/attrs.xml b/android/app/src/main/res/values/attrs.xml
new file mode 100644
index 00000000..e52391d2
--- /dev/null
+++ b/android/app/src/main/res/values/attrs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml
new file mode 100644
index 00000000..89cad66c
--- /dev/null
+++ b/android/app/src/main/res/values/colors.xml
@@ -0,0 +1,7 @@
+
+ #FF039BE5
+ #FF01579B
+ #FF40C4FF
+ #FF00B0FF
+ #66000000
+
\ No newline at end of file
diff --git a/android/app/src/main/res/values/dimens.xml b/android/app/src/main/res/values/dimens.xml
new file mode 100644
index 00000000..125df871
--- /dev/null
+++ b/android/app/src/main/res/values/dimens.xml
@@ -0,0 +1,3 @@
+
+ 16dp
+
\ No newline at end of file
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
new file mode 100644
index 00000000..a913c2fc
--- /dev/null
+++ b/android/app/src/main/res/values/strings.xml
@@ -0,0 +1,49 @@
+
+ VideoPlayerActivity
+ Dummy Button
+ DUMMY\nCONTENT
+ MyTestActivity
+
+ First Fragment
+ Second Fragment
+ Next
+ Previous
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam in scelerisque sem. Mauris
+ volutpat, dolor id interdum ullamcorper, risus dolor egestas lectus, sit amet mattis purus
+ dui nec risus. Maecenas non sodales nisi, vel dictum dolor. Class aptent taciti sociosqu ad
+ litora torquent per conubia nostra, per inceptos himenaeos. Suspendisse blandit eleifend
+ diam, vel rutrum tellus vulputate quis. Aliquam eget libero aliquet, imperdiet nisl a,
+ ornare ex. Sed rhoncus est ut libero porta lobortis. Fusce in dictum tellus.\n\n
+ Suspendisse interdum ornare ante. Aliquam nec cursus lorem. Morbi id magna felis. Vivamus
+ egestas, est a condimentum egestas, turpis nisl iaculis ipsum, in dictum tellus dolor sed
+ neque. Morbi tellus erat, dapibus ut sem a, iaculis tincidunt dui. Interdum et malesuada
+ fames ac ante ipsum primis in faucibus. Curabitur et eros porttitor, ultricies urna vitae,
+ molestie nibh. Phasellus at commodo eros, non aliquet metus. Sed maximus nisl nec dolor
+ bibendum, vel congue leo egestas.\n\n
+ Sed interdum tortor nibh, in sagittis risus mollis quis. Curabitur mi odio, condimentum sit
+ amet auctor at, mollis non turpis. Nullam pretium libero vestibulum, finibus orci vel,
+ molestie quam. Fusce blandit tincidunt nulla, quis sollicitudin libero facilisis et. Integer
+ interdum nunc ligula, et fermentum metus hendrerit id. Vestibulum lectus felis, dictum at
+ lacinia sit amet, tristique id quam. Cras eu consequat dui. Suspendisse sodales nunc ligula,
+ in lobortis sem porta sed. Integer id ultrices magna, in luctus elit. Sed a pellentesque
+ est.\n\n
+ Aenean nunc velit, lacinia sed dolor sed, ultrices viverra nulla. Etiam a venenatis nibh.
+ Morbi laoreet, tortor sed facilisis varius, nibh orci rhoncus nulla, id elementum leo dui
+ non lorem. Nam mollis ipsum quis auctor varius. Quisque elementum eu libero sed commodo. In
+ eros nisl, imperdiet vel imperdiet et, scelerisque a mauris. Pellentesque varius ex nunc,
+ quis imperdiet eros placerat ac. Duis finibus orci et est auctor tincidunt. Sed non viverra
+ ipsum. Nunc quis augue egestas, cursus lorem at, molestie sem. Morbi a consectetur ipsum, a
+ placerat diam. Etiam vulputate dignissim convallis. Integer faucibus mauris sit amet finibus
+ convallis.\n\n
+ Phasellus in aliquet mi. Pellentesque habitant morbi tristique senectus et netus et
+ malesuada fames ac turpis egestas. In volutpat arcu ut felis sagittis, in finibus massa
+ gravida. Pellentesque id tellus orci. Integer dictum, lorem sed efficitur ullamcorper,
+ libero justo consectetur ipsum, in mollis nisl ex sed nisl. Donec maximus ullamcorper
+ sodales. Praesent bibendum rhoncus tellus nec feugiat. In a ornare nulla. Donec rhoncus
+ libero vel nunc consequat, quis tincidunt nisl eleifend. Cras bibendum enim a justo luctus
+ vestibulum. Fusce dictum libero quis erat maximus, vitae volutpat diam dignissim.
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml
index d460d1e9..11ea92e2 100644
--- a/android/app/src/main/res/values/styles.xml
+++ b/android/app/src/main/res/values/styles.xml
@@ -15,4 +15,12 @@
+
+
+
diff --git a/android/app/src/main/res/values/themes.xml b/android/app/src/main/res/values/themes.xml
new file mode 100644
index 00000000..225bece0
--- /dev/null
+++ b/android/app/src/main/res/values/themes.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml
index 0820d81a..f880684a 100644
--- a/android/app/src/profile/AndroidManifest.xml
+++ b/android/app/src/profile/AndroidManifest.xml
@@ -1,5 +1,4 @@
-
+
diff --git a/android/build.gradle b/android/build.gradle
index d302341a..5c031b14 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -1,17 +1,3 @@
-buildscript {
- ext.kotlin_version = '1.3.50'
- repositories {
- google()
- mavenCentral()
- }
-
- dependencies {
- classpath 'com.android.tools.build:gradle:4.1.0'
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
- classpath 'com.google.gms:google-services:4.3.10'
- }
-}
-
allprojects {
repositories {
google()
@@ -27,6 +13,18 @@ subprojects {
project.evaluationDependsOn(':app')
}
-task clean(type: Delete) {
+tasks.register("clean", Delete) {
delete rootProject.buildDir
}
+
+//rootProject.allprojects {
+// subprojects {
+// project.configurations.all {
+// resolutionStrategy.eachDependency { details ->
+// if (details.requested.group == 'androidx.core' && !details.requested.name.contains('androidx')) {
+// details.useVersion "1.0.1"
+// }
+// }
+// }
+// }
+//}
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
index bc6a58af..c4623b06 100644
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
\ No newline at end of file
diff --git a/android/settings.gradle b/android/settings.gradle
index 44e62bcf..8b3ec872 100644
--- a/android/settings.gradle
+++ b/android/settings.gradle
@@ -1,11 +1,25 @@
-include ':app'
+pluginManagement {
+ def flutterSdkPath = {
+ def properties = new Properties()
+ file("local.properties").withInputStream { properties.load(it) }
+ def flutterSdkPath = properties.getProperty("flutter.sdk")
+ assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+ return flutterSdkPath
+ }()
-def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
-def properties = new Properties()
+ includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
-assert localPropertiesFile.exists()
-localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
+ repositories {
+ google()
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
-def flutterSdkPath = properties.getProperty("flutter.sdk")
-assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
-apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
+plugins {
+ id "dev.flutter.flutter-plugin-loader" version "1.0.0"
+ id "com.android.application" version "7.2.0" apply false // Replace with your AGP version if needed
+ id "org.jetbrains.kotlin.android" version "1.9.23" apply false // Replace with your Kotlin version if needed
+}
+
+include ":app"
\ No newline at end of file
diff --git a/assets/branding/three_shorts_icon.png b/assets/branding/three_shorts_icon.png
new file mode 100644
index 00000000..685c5c29
Binary files /dev/null and b/assets/branding/three_shorts_icon.png differ
diff --git a/assets/ctt-logo.png b/assets/ctt-logo.png
new file mode 100644
index 00000000..1740e5c7
Binary files /dev/null and b/assets/ctt-logo.png differ
diff --git a/assets/hive-keychain-image.png b/assets/hive-keychain-image.png
new file mode 100644
index 00000000..c5bfe873
Binary files /dev/null and b/assets/hive-keychain-image.png differ
diff --git a/assets/hive_auth_button.png b/assets/hive_auth_button.png
new file mode 100644
index 00000000..a6d8330e
Binary files /dev/null and b/assets/hive_auth_button.png differ
diff --git a/assets/hiveauth_icon.png b/assets/hiveauth_icon.png
new file mode 100644
index 00000000..54e9bb9e
Binary files /dev/null and b/assets/hiveauth_icon.png differ
diff --git a/assets/ipfs-logo.png b/assets/ipfs-logo.png
new file mode 100644
index 00000000..5d26eb26
Binary files /dev/null and b/assets/ipfs-logo.png differ
diff --git a/assets/pod-cast-logo-round.png b/assets/pod-cast-logo-round.png
new file mode 100644
index 00000000..c48aaea2
Binary files /dev/null and b/assets/pod-cast-logo-round.png differ
diff --git a/assets/podcast-index.jpg b/assets/podcast-index.jpg
new file mode 100644
index 00000000..47472c97
Binary files /dev/null and b/assets/podcast-index.jpg differ
diff --git a/assets/ps_guide_1.png b/assets/ps_guide_1.png
new file mode 100644
index 00000000..1d99c6a0
Binary files /dev/null and b/assets/ps_guide_1.png differ
diff --git a/assets/ps_guide_2.png b/assets/ps_guide_2.png
new file mode 100644
index 00000000..bf3461ad
Binary files /dev/null and b/assets/ps_guide_2.png differ
diff --git a/devtools_options.yaml b/devtools_options.yaml
new file mode 100644
index 00000000..fa0b357c
--- /dev/null
+++ b/devtools_options.yaml
@@ -0,0 +1,3 @@
+description: This file stores settings for Dart & Flutter DevTools.
+documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
+extensions:
diff --git a/flutter_01.log b/flutter_01.log
new file mode 100644
index 00000000..4ae32a64
--- /dev/null
+++ b/flutter_01.log
@@ -0,0 +1,118 @@
+Flutter crash report.
+Please report a bug at https://github.com/flutter/flutter/issues.
+
+## command
+
+flutter pub get
+
+## exception
+
+PathNotFoundException: PathNotFoundException: Cannot open file, path = '/Applications/flutter/flutter/version' (OS Error: No such file or directory, errno = 2)
+
+```
+#0 _File.throwIfError (dart:io/file_impl.dart:629:7)
+#1 _File.openSync (dart:io/file_impl.dart:473:5)
+#2 _File.readAsBytesSync (dart:io/file_impl.dart:533:18)
+#3 _File.readAsStringSync (dart:io/file_impl.dart:578:18)
+#4 ForwardingFile.readAsStringSync (package:file/src/forwarding/forwarding_file.dart:99:16)
+#5 ErrorHandlingFile.readAsStringSync. (package:flutter_tools/src/base/error_handling_io.dart:222:22)
+#6 _runSync (package:flutter_tools/src/base/error_handling_io.dart:600:14)
+#7 ErrorHandlingFile.readAsStringSync (package:flutter_tools/src/base/error_handling_io.dart:221:12)
+#8 _DefaultPub.get (package:flutter_tools/src/dart/pub.dart:360:50)
+
+#9 PackagesGetCommand._runPubGet (package:flutter_tools/src/commands/packages.dart:140:7)
+
+#10 PackagesGetCommand.runCommand (package:flutter_tools/src/commands/packages.dart:175:5)
+
+#11 FlutterCommand.run. (package:flutter_tools/src/runner/flutter_command.dart:1257:27)
+
+#12 AppContext.run. (package:flutter_tools/src/base/context.dart:150:19)
+
+#13 CommandRunner.runCommand (package:args/command_runner.dart:209:13)
+
+#14 FlutterCommandRunner.runCommand. (package:flutter_tools/src/runner/flutter_command_runner.dart:283:9)
+
+#15 AppContext.run. (package:flutter_tools/src/base/context.dart:150:19)
+
+#16 FlutterCommandRunner.runCommand (package:flutter_tools/src/runner/flutter_command_runner.dart:229:5)
+
+#17 run.. (package:flutter_tools/runner.dart:64:9)
+
+#18 AppContext.run. (package:flutter_tools/src/base/context.dart:150:19)
+
+#19 main (package:flutter_tools/executable.dart:91:3)
+
+```
+
+## flutter doctor
+
+```
+[☠] Flutter (the doctor check crashed)
+ ✗ Due to an error, the doctor check did not complete. If the error message below is not helpful, please let us know about this issue at https://github.com/flutter/flutter/issues.
+ ✗ Exception: Could not find directory at /Applications/flutter/flutter/bin/cache/dart-sdk/bin/resources/devtools
+ • #0 Cache.devToolsVersion (package:flutter_tools/src/cache.dart:384:9)
+ #1 _DefaultDoctorValidatorsProvider.validators. (package:flutter_tools/src/doctor.dart:126:46)
+ #2 FlutterValidator.validate (package:flutter_tools/src/doctor.dart:530:84)
+ #3 Doctor.startValidatorTasks. (package:flutter_tools/src/doctor.dart:250:72)
+ #4 asyncGuard. (package:flutter_tools/src/base/async_guard.dart:111:32)
+ #5 _rootRun (dart:async/zone.dart:1398:13)
+ #6 _CustomZone.run (dart:async/zone.dart:1300:19)
+ #7 _runZoned (dart:async/zone.dart:1803:10)
+ #8 runZonedGuarded (dart:async/zone.dart:1791:12)
+ #9 runZoned (dart:async/zone.dart:1743:12)
+ #10 asyncGuard (package:flutter_tools/src/base/async_guard.dart:109:3)
+ #11 Doctor.startValidatorTasks (package:flutter_tools/src/doctor.dart:242:9)
+ #12 DoctorText._validatorTasks (package:flutter_tools/src/doctor.dart:739:60)
+ #13 DoctorText._validatorTasks (package:flutter_tools/src/doctor.dart)
+ #14 DoctorText._runDiagnosis (package:flutter_tools/src/doctor.dart:743:53)
+ #15 DoctorText.text (package:flutter_tools/src/doctor.dart:735:36)
+ #16 DoctorText.text (package:flutter_tools/src/doctor.dart)
+ #17 _createLocalCrashReport (package:flutter_tools/runner.dart:206:51)
+ #18 _handleToolError (package:flutter_tools/runner.dart:168:31)
+
+ #19 AppContext.run. (package:flutter_tools/src/base/context.dart:150:19)
+
+ #20 main (package:flutter_tools/executable.dart:91:3)
+
+
+
+[!] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
+ • Android SDK at /Users/sagar/Library/Android/sdk
+ • Platform android-33, build-tools 33.0.0
+ • Java binary at: /Library/Java/JavaVirtualMachines/temurin-8.jdk/Contents/Home/bin/java
+ • Java version OpenJDK Runtime Environment (Temurin)(build 1.8.0_322-b06)
+ ✗ Android license status unknown.
+ Run `flutter doctor --android-licenses` to accept the SDK licenses.
+ See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
+
+[✓] Xcode - develop for iOS and macOS (Xcode 14.2)
+ • Xcode at /Applications/Xcode.app/Contents/Developer
+ • Build 14C18
+ • CocoaPods version 1.11.3
+
+[✓] Chrome - develop for the web
+ • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
+
+[!] Android Studio (version 2022.1)
+ • Android Studio at /Applications/Android Studio.app/Contents
+ • Flutter plugin can be installed from:
+ 🔨 https://plugins.jetbrains.com/plugin/9212-flutter
+ • Dart plugin can be installed from:
+ 🔨 https://plugins.jetbrains.com/plugin/6351-dart
+ ✗ Unable to find bundled Java version.
+ • Try updating or re-installing Android Studio.
+
+[✓] VS Code (version 1.74.3)
+ • VS Code at /Applications/Visual Studio Code.app/Contents
+ • Flutter extension version 3.58.0
+
+[✓] Connected device (3 available)
+ • iPhone 14 Pro (mobile) • 01D7AC4F-11B8-456A-8FD4-8275C0814F45 • ios • com.apple.CoreSimulator.SimRuntime.iOS-16-2 (simulator)
+ • macOS (desktop) • macos • darwin-arm64 • macOS 13.1 22C65 darwin-arm64
+ • Chrome (web) • chrome • web-javascript • Google Chrome 109.0.5414.119
+
+[✓] HTTP Host Availability
+ • All required HTTP hosts are available
+
+! Doctor found issues in 3 categories.
+```
diff --git a/ios/.DS_Store b/ios/.DS_Store
index cc251821..da90ef3e 100644
Binary files a/ios/.DS_Store and b/ios/.DS_Store differ
diff --git a/ios/.bundle/config b/ios/.bundle/config
new file mode 100644
index 00000000..23692288
--- /dev/null
+++ b/ios/.bundle/config
@@ -0,0 +1,2 @@
+---
+BUNDLE_PATH: "vendor/bundle"
diff --git a/ios/.gitignore b/ios/.gitignore
index 7a7f9873..c65d6368 100644
--- a/ios/.gitignore
+++ b/ios/.gitignore
@@ -1,3 +1,7 @@
+fastlane
+*.ipa
+*.app.dSYM.zip
+
**/dgph
*.mode1v3
*.mode2v3
@@ -31,4 +35,4 @@ Runner/GeneratedPluginRegistrant.*
!default.mode1v3
!default.mode2v3
!default.pbxuser
-!default.perspectivev3
+!default.perspectivev3
\ No newline at end of file
diff --git a/ios/Development_com.example.acela.mobileprovision b/ios/Development_com.example.acela.mobileprovision
new file mode 100644
index 00000000..22952a57
Binary files /dev/null and b/ios/Development_com.example.acela.mobileprovision differ
diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist
index 8d4492f9..7c569640 100644
--- a/ios/Flutter/AppFrameworkInfo.plist
+++ b/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 9.0
+ 12.0
diff --git a/ios/Gemfile b/ios/Gemfile
new file mode 100644
index 00000000..d554c27a
--- /dev/null
+++ b/ios/Gemfile
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+
+gem "fastlane"
+# gem "rails"
diff --git a/ios/Gemfile.lock b/ios/Gemfile.lock
new file mode 100644
index 00000000..6421b260
--- /dev/null
+++ b/ios/Gemfile.lock
@@ -0,0 +1,218 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ CFPropertyList (3.0.6)
+ rexml
+ addressable (2.8.5)
+ public_suffix (>= 2.0.2, < 6.0)
+ artifactory (3.0.15)
+ atomos (0.1.3)
+ aws-eventstream (1.2.0)
+ aws-partitions (1.805.0)
+ aws-sdk-core (3.180.3)
+ aws-eventstream (~> 1, >= 1.0.2)
+ aws-partitions (~> 1, >= 1.651.0)
+ aws-sigv4 (~> 1.5)
+ jmespath (~> 1, >= 1.6.1)
+ aws-sdk-kms (1.71.0)
+ aws-sdk-core (~> 3, >= 3.177.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-s3 (1.132.1)
+ aws-sdk-core (~> 3, >= 3.179.0)
+ aws-sdk-kms (~> 1)
+ aws-sigv4 (~> 1.6)
+ aws-sigv4 (1.6.0)
+ aws-eventstream (~> 1, >= 1.0.2)
+ babosa (1.0.4)
+ claide (1.1.0)
+ colored (1.2)
+ colored2 (3.1.2)
+ commander (4.6.0)
+ highline (~> 2.0.0)
+ declarative (0.0.20)
+ digest-crc (0.6.5)
+ rake (>= 12.0.0, < 14.0.0)
+ domain_name (0.5.20190701)
+ unf (>= 0.0.5, < 1.0.0)
+ dotenv (2.8.1)
+ emoji_regex (3.2.3)
+ excon (0.100.0)
+ faraday (1.10.3)
+ faraday-em_http (~> 1.0)
+ faraday-em_synchrony (~> 1.0)
+ faraday-excon (~> 1.1)
+ faraday-httpclient (~> 1.0)
+ faraday-multipart (~> 1.0)
+ faraday-net_http (~> 1.0)
+ faraday-net_http_persistent (~> 1.0)
+ faraday-patron (~> 1.0)
+ faraday-rack (~> 1.0)
+ faraday-retry (~> 1.0)
+ ruby2_keywords (>= 0.0.4)
+ faraday-cookie_jar (0.0.7)
+ faraday (>= 0.8.0)
+ http-cookie (~> 1.0.0)
+ faraday-em_http (1.0.0)
+ faraday-em_synchrony (1.0.0)
+ faraday-excon (1.1.0)
+ faraday-httpclient (1.0.1)
+ faraday-multipart (1.0.4)
+ multipart-post (~> 2)
+ faraday-net_http (1.0.1)
+ faraday-net_http_persistent (1.2.0)
+ faraday-patron (1.0.0)
+ faraday-rack (1.0.0)
+ faraday-retry (1.0.3)
+ faraday_middleware (1.2.0)
+ faraday (~> 1.0)
+ fastimage (2.2.7)
+ fastlane (2.214.0)
+ CFPropertyList (>= 2.3, < 4.0.0)
+ addressable (>= 2.8, < 3.0.0)
+ artifactory (~> 3.0)
+ aws-sdk-s3 (~> 1.0)
+ babosa (>= 1.0.3, < 2.0.0)
+ bundler (>= 1.12.0, < 3.0.0)
+ colored
+ commander (~> 4.6)
+ dotenv (>= 2.1.1, < 3.0.0)
+ emoji_regex (>= 0.1, < 4.0)
+ excon (>= 0.71.0, < 1.0.0)
+ faraday (~> 1.0)
+ faraday-cookie_jar (~> 0.0.6)
+ faraday_middleware (~> 1.0)
+ fastimage (>= 2.1.0, < 3.0.0)
+ gh_inspector (>= 1.1.2, < 2.0.0)
+ google-apis-androidpublisher_v3 (~> 0.3)
+ google-apis-playcustomapp_v1 (~> 0.1)
+ google-cloud-storage (~> 1.31)
+ highline (~> 2.0)
+ json (< 3.0.0)
+ jwt (>= 2.1.0, < 3)
+ mini_magick (>= 4.9.4, < 5.0.0)
+ multipart-post (>= 2.0.0, < 3.0.0)
+ naturally (~> 2.2)
+ optparse (~> 0.1.1)
+ plist (>= 3.1.0, < 4.0.0)
+ rubyzip (>= 2.0.0, < 3.0.0)
+ security (= 0.1.3)
+ simctl (~> 1.6.3)
+ terminal-notifier (>= 2.0.0, < 3.0.0)
+ terminal-table (>= 1.4.5, < 2.0.0)
+ tty-screen (>= 0.6.3, < 1.0.0)
+ tty-spinner (>= 0.8.0, < 1.0.0)
+ word_wrap (~> 1.0.0)
+ xcodeproj (>= 1.13.0, < 2.0.0)
+ xcpretty (~> 0.3.0)
+ xcpretty-travis-formatter (>= 0.0.3)
+ gh_inspector (1.1.3)
+ google-apis-androidpublisher_v3 (0.48.0)
+ google-apis-core (>= 0.11.0, < 2.a)
+ google-apis-core (0.11.1)
+ addressable (~> 2.5, >= 2.5.1)
+ googleauth (>= 0.16.2, < 2.a)
+ httpclient (>= 2.8.1, < 3.a)
+ mini_mime (~> 1.0)
+ representable (~> 3.0)
+ retriable (>= 2.0, < 4.a)
+ rexml
+ webrick
+ google-apis-iamcredentials_v1 (0.17.0)
+ google-apis-core (>= 0.11.0, < 2.a)
+ google-apis-playcustomapp_v1 (0.13.0)
+ google-apis-core (>= 0.11.0, < 2.a)
+ google-apis-storage_v1 (0.19.0)
+ google-apis-core (>= 0.9.0, < 2.a)
+ google-cloud-core (1.6.0)
+ google-cloud-env (~> 1.0)
+ google-cloud-errors (~> 1.0)
+ google-cloud-env (1.6.0)
+ faraday (>= 0.17.3, < 3.0)
+ google-cloud-errors (1.3.1)
+ google-cloud-storage (1.44.0)
+ addressable (~> 2.8)
+ digest-crc (~> 0.4)
+ google-apis-iamcredentials_v1 (~> 0.1)
+ google-apis-storage_v1 (~> 0.19.0)
+ google-cloud-core (~> 1.6)
+ googleauth (>= 0.16.2, < 2.a)
+ mini_mime (~> 1.0)
+ googleauth (1.7.0)
+ faraday (>= 0.17.3, < 3.a)
+ jwt (>= 1.4, < 3.0)
+ memoist (~> 0.16)
+ multi_json (~> 1.11)
+ os (>= 0.9, < 2.0)
+ signet (>= 0.16, < 2.a)
+ highline (2.0.3)
+ http-cookie (1.0.5)
+ domain_name (~> 0.5)
+ httpclient (2.8.3)
+ jmespath (1.6.2)
+ json (2.6.3)
+ jwt (2.7.1)
+ memoist (0.16.2)
+ mini_magick (4.12.0)
+ mini_mime (1.1.5)
+ multi_json (1.15.0)
+ multipart-post (2.3.0)
+ nanaimo (0.3.0)
+ naturally (2.2.1)
+ optparse (0.1.1)
+ os (1.1.4)
+ plist (3.7.0)
+ public_suffix (5.0.3)
+ rake (13.0.6)
+ representable (3.2.0)
+ declarative (< 0.1.0)
+ trailblazer-option (>= 0.1.1, < 0.2.0)
+ uber (< 0.2.0)
+ retriable (3.1.2)
+ rexml (3.2.6)
+ rouge (2.0.7)
+ ruby2_keywords (0.0.5)
+ rubyzip (2.3.2)
+ security (0.1.3)
+ signet (0.17.0)
+ addressable (~> 2.8)
+ faraday (>= 0.17.5, < 3.a)
+ jwt (>= 1.5, < 3.0)
+ multi_json (~> 1.10)
+ simctl (1.6.10)
+ CFPropertyList
+ naturally
+ terminal-notifier (2.0.0)
+ terminal-table (1.8.0)
+ unicode-display_width (~> 1.1, >= 1.1.1)
+ trailblazer-option (0.1.2)
+ tty-cursor (0.7.1)
+ tty-screen (0.8.1)
+ tty-spinner (0.9.3)
+ tty-cursor (~> 0.7)
+ uber (0.1.0)
+ unf (0.1.4)
+ unf_ext
+ unf_ext (0.0.8.2)
+ unicode-display_width (1.8.0)
+ webrick (1.8.1)
+ word_wrap (1.0.0)
+ xcodeproj (1.22.0)
+ CFPropertyList (>= 2.3.3, < 4.0)
+ atomos (~> 0.1.3)
+ claide (>= 1.0.2, < 2.0)
+ colored2 (~> 3.1)
+ nanaimo (~> 0.3.0)
+ rexml (~> 3.2.4)
+ xcpretty (0.3.0)
+ rouge (~> 2.0.7)
+ xcpretty-travis-formatter (1.0.1)
+ xcpretty (~> 0.2, >= 0.0.7)
+
+PLATFORMS
+ arm64-darwin-21
+
+DEPENDENCIES
+ fastlane
+
+BUNDLED WITH
+ 2.3.14
diff --git a/ios/Podfile b/ios/Podfile
index 6b7880c5..ea9d9b81 100644
--- a/ios/Podfile
+++ b/ios/Podfile
@@ -30,6 +30,7 @@ flutter_ios_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
+ pod 'FYVideoCompressor'
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 0c649f2f..f1339ccf 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -1,22 +1,450 @@
PODS:
+ - assets_audio_player (0.0.1):
+ - Flutter
+ - audio_service (0.0.1):
+ - Flutter
+ - audio_session (0.0.1):
+ - Flutter
+ - better_player (0.0.1):
+ - Cache (~> 6.0.0)
+ - Flutter
+ - GCDWebServer
+ - HLSCachingReverseProxyServer
+ - PINCache
+ - Cache (6.0.0)
+ - croppy (0.0.1):
+ - Flutter
+ - device_info_plus (0.0.1):
+ - Flutter
+ - DKImagePickerController/Core (4.3.9):
+ - DKImagePickerController/ImageDataManager
+ - DKImagePickerController/Resource
+ - DKImagePickerController/ImageDataManager (4.3.9)
+ - DKImagePickerController/PhotoGallery (4.3.9):
+ - DKImagePickerController/Core
+ - DKPhotoGallery
+ - DKImagePickerController/Resource (4.3.9)
+ - DKPhotoGallery (0.0.19):
+ - DKPhotoGallery/Core (= 0.0.19)
+ - DKPhotoGallery/Model (= 0.0.19)
+ - DKPhotoGallery/Preview (= 0.0.19)
+ - DKPhotoGallery/Resource (= 0.0.19)
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Core (0.0.19):
+ - DKPhotoGallery/Model
+ - DKPhotoGallery/Preview
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Model (0.0.19):
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Preview (0.0.19):
+ - DKPhotoGallery/Model
+ - DKPhotoGallery/Resource
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Resource (0.0.19):
+ - SDWebImage
+ - SwiftyGif
+ - ffmpeg-kit-ios-https-gpl (6.0)
+ - ffmpeg_kit_flutter_https_gpl (6.0.3):
+ - ffmpeg_kit_flutter_https_gpl/https-gpl (= 6.0.3)
+ - Flutter
+ - ffmpeg_kit_flutter_https_gpl/https-gpl (6.0.3):
+ - ffmpeg-kit-ios-https-gpl (= 6.0)
+ - Flutter
+ - file_picker (0.0.1):
+ - DKImagePickerController/PhotoGallery
+ - Flutter
+ - Firebase/Analytics (11.6.0):
+ - Firebase/Core
+ - Firebase/Core (11.6.0):
+ - Firebase/CoreOnly
+ - FirebaseAnalytics (~> 11.6.0)
+ - Firebase/CoreOnly (11.6.0):
+ - FirebaseCore (~> 11.6.0)
+ - Firebase/Crashlytics (11.6.0):
+ - Firebase/CoreOnly
+ - FirebaseCrashlytics (~> 11.6.0)
+ - firebase_analytics (11.4.0):
+ - Firebase/Analytics (= 11.6.0)
+ - firebase_core
+ - Flutter
+ - firebase_core (3.10.0):
+ - Firebase/CoreOnly (= 11.6.0)
+ - Flutter
+ - firebase_crashlytics (4.3.0):
+ - Firebase/Crashlytics (= 11.6.0)
+ - firebase_core
+ - Flutter
+ - FirebaseAnalytics (11.6.0):
+ - FirebaseAnalytics/AdIdSupport (= 11.6.0)
+ - FirebaseCore (~> 11.6.0)
+ - FirebaseInstallations (~> 11.0)
+ - GoogleUtilities/AppDelegateSwizzler (~> 8.0)
+ - GoogleUtilities/MethodSwizzler (~> 8.0)
+ - GoogleUtilities/Network (~> 8.0)
+ - "GoogleUtilities/NSData+zlib (~> 8.0)"
+ - nanopb (~> 3.30910.0)
+ - FirebaseAnalytics/AdIdSupport (11.6.0):
+ - FirebaseCore (~> 11.6.0)
+ - FirebaseInstallations (~> 11.0)
+ - GoogleAppMeasurement (= 11.6.0)
+ - GoogleUtilities/AppDelegateSwizzler (~> 8.0)
+ - GoogleUtilities/MethodSwizzler (~> 8.0)
+ - GoogleUtilities/Network (~> 8.0)
+ - "GoogleUtilities/NSData+zlib (~> 8.0)"
+ - nanopb (~> 3.30910.0)
+ - FirebaseCore (11.6.0):
+ - FirebaseCoreInternal (~> 11.6.0)
+ - GoogleUtilities/Environment (~> 8.0)
+ - GoogleUtilities/Logger (~> 8.0)
+ - FirebaseCoreExtension (11.6.0):
+ - FirebaseCore (~> 11.6.0)
+ - FirebaseCoreInternal (11.6.0):
+ - "GoogleUtilities/NSData+zlib (~> 8.0)"
+ - FirebaseCrashlytics (11.6.0):
+ - FirebaseCore (~> 11.6.0)
+ - FirebaseInstallations (~> 11.0)
+ - FirebaseRemoteConfigInterop (~> 11.0)
+ - FirebaseSessions (~> 11.0)
+ - GoogleDataTransport (~> 10.0)
+ - GoogleUtilities/Environment (~> 8.0)
+ - nanopb (~> 3.30910.0)
+ - PromisesObjC (~> 2.4)
+ - FirebaseInstallations (11.6.0):
+ - FirebaseCore (~> 11.6.0)
+ - GoogleUtilities/Environment (~> 8.0)
+ - GoogleUtilities/UserDefaults (~> 8.0)
+ - PromisesObjC (~> 2.4)
+ - FirebaseRemoteConfigInterop (11.6.0)
+ - FirebaseSessions (11.6.0):
+ - FirebaseCore (~> 11.6.0)
+ - FirebaseCoreExtension (~> 11.6.0)
+ - FirebaseInstallations (~> 11.0)
+ - GoogleDataTransport (~> 10.0)
+ - GoogleUtilities/Environment (~> 8.0)
+ - GoogleUtilities/UserDefaults (~> 8.0)
+ - nanopb (~> 3.30910.0)
+ - PromisesSwift (~> 2.1)
- Flutter (1.0.0)
- - video_player (0.0.1):
+ - flutter_downloader (0.0.1):
+ - Flutter
+ - flutter_secure_storage (6.0.0):
+ - Flutter
+ - FYVideoCompressor (0.0.9)
+ - GCDWebServer (3.5.4):
+ - GCDWebServer/Core (= 3.5.4)
+ - GCDWebServer/Core (3.5.4)
+ - GoogleAppMeasurement (11.6.0):
+ - GoogleAppMeasurement/AdIdSupport (= 11.6.0)
+ - GoogleUtilities/AppDelegateSwizzler (~> 8.0)
+ - GoogleUtilities/MethodSwizzler (~> 8.0)
+ - GoogleUtilities/Network (~> 8.0)
+ - "GoogleUtilities/NSData+zlib (~> 8.0)"
+ - nanopb (~> 3.30910.0)
+ - GoogleAppMeasurement/AdIdSupport (11.6.0):
+ - GoogleAppMeasurement/WithoutAdIdSupport (= 11.6.0)
+ - GoogleUtilities/AppDelegateSwizzler (~> 8.0)
+ - GoogleUtilities/MethodSwizzler (~> 8.0)
+ - GoogleUtilities/Network (~> 8.0)
+ - "GoogleUtilities/NSData+zlib (~> 8.0)"
+ - nanopb (~> 3.30910.0)
+ - GoogleAppMeasurement/WithoutAdIdSupport (11.6.0):
+ - GoogleUtilities/AppDelegateSwizzler (~> 8.0)
+ - GoogleUtilities/MethodSwizzler (~> 8.0)
+ - GoogleUtilities/Network (~> 8.0)
+ - "GoogleUtilities/NSData+zlib (~> 8.0)"
+ - nanopb (~> 3.30910.0)
+ - GoogleDataTransport (10.1.0):
+ - nanopb (~> 3.30910.0)
+ - PromisesObjC (~> 2.4)
+ - GoogleUtilities/AppDelegateSwizzler (8.0.2):
+ - GoogleUtilities/Environment
+ - GoogleUtilities/Logger
+ - GoogleUtilities/Network
+ - GoogleUtilities/Privacy
+ - GoogleUtilities/Environment (8.0.2):
+ - GoogleUtilities/Privacy
+ - GoogleUtilities/Logger (8.0.2):
+ - GoogleUtilities/Environment
+ - GoogleUtilities/Privacy
+ - GoogleUtilities/MethodSwizzler (8.0.2):
+ - GoogleUtilities/Logger
+ - GoogleUtilities/Privacy
+ - GoogleUtilities/Network (8.0.2):
+ - GoogleUtilities/Logger
+ - "GoogleUtilities/NSData+zlib"
+ - GoogleUtilities/Privacy
+ - GoogleUtilities/Reachability
+ - "GoogleUtilities/NSData+zlib (8.0.2)":
+ - GoogleUtilities/Privacy
+ - GoogleUtilities/Privacy (8.0.2)
+ - GoogleUtilities/Reachability (8.0.2):
+ - GoogleUtilities/Logger
+ - GoogleUtilities/Privacy
+ - GoogleUtilities/UserDefaults (8.0.2):
+ - GoogleUtilities/Logger
+ - GoogleUtilities/Privacy
+ - HLSCachingReverseProxyServer (0.1.0):
+ - GCDWebServer (~> 3.5)
+ - PINCache (>= 3.0.1-beta.3)
+ - image_picker_ios (0.0.1):
+ - Flutter
+ - images_picker (0.0.1):
- Flutter
+ - ZLPhotoBrowser (= 4.2.5)
+ - just_audio (0.0.1):
+ - Flutter
+ - libwebp (1.3.2):
+ - libwebp/demux (= 1.3.2)
+ - libwebp/mux (= 1.3.2)
+ - libwebp/sharpyuv (= 1.3.2)
+ - libwebp/webp (= 1.3.2)
+ - libwebp/demux (1.3.2):
+ - libwebp/webp
+ - libwebp/mux (1.3.2):
+ - libwebp/demux
+ - libwebp/sharpyuv (1.3.2)
+ - libwebp/webp (1.3.2):
+ - libwebp/sharpyuv
+ - nanopb (3.30910.0):
+ - nanopb/decode (= 3.30910.0)
+ - nanopb/encode (= 3.30910.0)
+ - nanopb/decode (3.30910.0)
+ - nanopb/encode (3.30910.0)
+ - package_info_plus (0.4.5):
+ - Flutter
+ - path_provider_foundation (0.0.1):
+ - Flutter
+ - FlutterMacOS
+ - permission_handler_apple (9.3.0):
+ - Flutter
+ - PINCache (3.0.4):
+ - PINCache/Arc-exception-safe (= 3.0.4)
+ - PINCache/Core (= 3.0.4)
+ - PINCache/Arc-exception-safe (3.0.4):
+ - PINCache/Core
+ - PINCache/Core (3.0.4):
+ - PINOperation (~> 1.2.3)
+ - PINOperation (1.2.3)
+ - PromisesObjC (2.4.0)
+ - PromisesSwift (2.4.0):
+ - PromisesObjC (= 2.4.0)
+ - SDWebImage (5.20.0):
+ - SDWebImage/Core (= 5.20.0)
+ - SDWebImage/Core (5.20.0)
+ - share_plus (0.0.1):
+ - Flutter
+ - shared_preferences_foundation (0.0.1):
+ - Flutter
+ - FlutterMacOS
+ - sqflite_darwin (0.0.4):
+ - Flutter
+ - FlutterMacOS
+ - SwiftyGif (5.4.5)
+ - url_launcher_ios (0.0.1):
+ - Flutter
+ - video_compress (0.3.0):
+ - Flutter
+ - video_player_avfoundation (0.0.1):
+ - Flutter
+ - FlutterMacOS
+ - video_thumbnail (0.0.1):
+ - Flutter
+ - libwebp
+ - wakelock_plus (0.0.1):
+ - Flutter
+ - webview_flutter_wkwebview (0.0.1):
+ - Flutter
+ - FlutterMacOS
+ - ZLPhotoBrowser (4.2.5):
+ - ZLPhotoBrowser/Core (= 4.2.5)
+ - ZLPhotoBrowser/Core (4.2.5)
DEPENDENCIES:
+ - assets_audio_player (from `.symlinks/plugins/assets_audio_player/ios`)
+ - audio_service (from `.symlinks/plugins/audio_service/ios`)
+ - audio_session (from `.symlinks/plugins/audio_session/ios`)
+ - better_player (from `.symlinks/plugins/better_player/ios`)
+ - croppy (from `.symlinks/plugins/croppy/ios`)
+ - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
+ - ffmpeg_kit_flutter_https_gpl (from `.symlinks/plugins/ffmpeg_kit_flutter_https_gpl/ios`)
+ - file_picker (from `.symlinks/plugins/file_picker/ios`)
+ - firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`)
+ - firebase_core (from `.symlinks/plugins/firebase_core/ios`)
+ - firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`)
- Flutter (from `Flutter`)
- - video_player (from `.symlinks/plugins/video_player/ios`)
+ - flutter_downloader (from `.symlinks/plugins/flutter_downloader/ios`)
+ - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
+ - FYVideoCompressor
+ - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
+ - images_picker (from `.symlinks/plugins/images_picker/ios`)
+ - just_audio (from `.symlinks/plugins/just_audio/ios`)
+ - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
+ - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
+ - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
+ - share_plus (from `.symlinks/plugins/share_plus/ios`)
+ - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
+ - sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
+ - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
+ - video_compress (from `.symlinks/plugins/video_compress/ios`)
+ - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`)
+ - video_thumbnail (from `.symlinks/plugins/video_thumbnail/ios`)
+ - wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
+ - webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/darwin`)
+
+SPEC REPOS:
+ trunk:
+ - Cache
+ - DKImagePickerController
+ - DKPhotoGallery
+ - ffmpeg-kit-ios-https-gpl
+ - Firebase
+ - FirebaseAnalytics
+ - FirebaseCore
+ - FirebaseCoreExtension
+ - FirebaseCoreInternal
+ - FirebaseCrashlytics
+ - FirebaseInstallations
+ - FirebaseRemoteConfigInterop
+ - FirebaseSessions
+ - FYVideoCompressor
+ - GCDWebServer
+ - GoogleAppMeasurement
+ - GoogleDataTransport
+ - GoogleUtilities
+ - HLSCachingReverseProxyServer
+ - libwebp
+ - nanopb
+ - PINCache
+ - PINOperation
+ - PromisesObjC
+ - PromisesSwift
+ - SDWebImage
+ - SwiftyGif
+ - ZLPhotoBrowser
EXTERNAL SOURCES:
+ assets_audio_player:
+ :path: ".symlinks/plugins/assets_audio_player/ios"
+ audio_service:
+ :path: ".symlinks/plugins/audio_service/ios"
+ audio_session:
+ :path: ".symlinks/plugins/audio_session/ios"
+ better_player:
+ :path: ".symlinks/plugins/better_player/ios"
+ croppy:
+ :path: ".symlinks/plugins/croppy/ios"
+ device_info_plus:
+ :path: ".symlinks/plugins/device_info_plus/ios"
+ ffmpeg_kit_flutter_https_gpl:
+ :path: ".symlinks/plugins/ffmpeg_kit_flutter_https_gpl/ios"
+ file_picker:
+ :path: ".symlinks/plugins/file_picker/ios"
+ firebase_analytics:
+ :path: ".symlinks/plugins/firebase_analytics/ios"
+ firebase_core:
+ :path: ".symlinks/plugins/firebase_core/ios"
+ firebase_crashlytics:
+ :path: ".symlinks/plugins/firebase_crashlytics/ios"
Flutter:
:path: Flutter
- video_player:
- :path: ".symlinks/plugins/video_player/ios"
+ flutter_downloader:
+ :path: ".symlinks/plugins/flutter_downloader/ios"
+ flutter_secure_storage:
+ :path: ".symlinks/plugins/flutter_secure_storage/ios"
+ image_picker_ios:
+ :path: ".symlinks/plugins/image_picker_ios/ios"
+ images_picker:
+ :path: ".symlinks/plugins/images_picker/ios"
+ just_audio:
+ :path: ".symlinks/plugins/just_audio/ios"
+ package_info_plus:
+ :path: ".symlinks/plugins/package_info_plus/ios"
+ path_provider_foundation:
+ :path: ".symlinks/plugins/path_provider_foundation/darwin"
+ permission_handler_apple:
+ :path: ".symlinks/plugins/permission_handler_apple/ios"
+ share_plus:
+ :path: ".symlinks/plugins/share_plus/ios"
+ shared_preferences_foundation:
+ :path: ".symlinks/plugins/shared_preferences_foundation/darwin"
+ sqflite_darwin:
+ :path: ".symlinks/plugins/sqflite_darwin/darwin"
+ url_launcher_ios:
+ :path: ".symlinks/plugins/url_launcher_ios/ios"
+ video_compress:
+ :path: ".symlinks/plugins/video_compress/ios"
+ video_player_avfoundation:
+ :path: ".symlinks/plugins/video_player_avfoundation/darwin"
+ video_thumbnail:
+ :path: ".symlinks/plugins/video_thumbnail/ios"
+ wakelock_plus:
+ :path: ".symlinks/plugins/wakelock_plus/ios"
+ webview_flutter_wkwebview:
+ :path: ".symlinks/plugins/webview_flutter_wkwebview/darwin"
SPEC CHECKSUMS:
- Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
- video_player: ecd305f42e9044793efd34846e1ce64c31ea6fcb
+ assets_audio_player: ae418728ee1b31f11556504fda8034639e20ce44
+ audio_service: 2023a4a1bdb2fd1443e7b00bdbdb1baa321525db
+ audio_session: f08db0697111ac84ba46191b55488c0563bb29c6
+ better_player: 472a1f3471b8991bde82327c91498b0f7934245d
+ Cache: 4ca7e00363fca5455f26534e5607634c820ffc2d
+ croppy: 979e8ddc254f4642bffe7d52dc7193354b27ba30
+ device_info_plus: 71ffc6ab7634ade6267c7a93088ed7e4f74e5896
+ DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
+ DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
+ ffmpeg-kit-ios-https-gpl: 0caef23dca1bdb18fe6f2e1cd43d02d5978c4c2e
+ ffmpeg_kit_flutter_https_gpl: 9ac316d69f8c5e30aa1ff6b9f76c4eb284b385f9
+ file_picker: 5f42b9d5580e30b57b4863f9d94b448016b702e5
+ Firebase: 374a441a91ead896215703a674d58cdb3e9d772b
+ firebase_analytics: a5c6ef5a435d22870fe3cfdcb424f390f56ff752
+ firebase_core: 2337982fb78ee4d8d91e608b0a3d4f44346a93c8
+ firebase_crashlytics: 3b6a9a9cbdc5ab92afaf9b206e52c79c2321a0d4
+ FirebaseAnalytics: 7114c698cac995602e3b1b96663473e50d54d6e7
+ FirebaseCore: 48b0dd707581cf9c1a1220da68223fb0a562afaa
+ FirebaseCoreExtension: 2d77d6430c16cf43ca2b04608302ed02b3598361
+ FirebaseCoreInternal: d98ab91e2d80a56d7b246856a8885443b302c0c2
+ FirebaseCrashlytics: b21c665fb50138766480bce73ebdb1aa30f7f300
+ FirebaseInstallations: efc0946fc756e4d22d8113f7c761948120322e8c
+ FirebaseRemoteConfigInterop: e75e348953352a000331eb77caf01e424248e176
+ FirebaseSessions: 9529d14180868e29a8da164b3a729c036204918b
+ Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
+ flutter_downloader: 78da0da1084e709cbfd3b723c7ea349c71681f09
+ flutter_secure_storage: 2c2ff13db9e0a5647389bff88b0ecac56e3f3418
+ FYVideoCompressor: 80e2a90bbc118044038b37b8442f23084c5698bf
+ GCDWebServer: 2c156a56c8226e2d5c0c3f208a3621ccffbe3ce4
+ GoogleAppMeasurement: 6a9e6317b6a6d810ad03d4a66564ca6c4c5818a3
+ GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
+ GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
+ HLSCachingReverseProxyServer: 59935e1e0244ad7f3375d75b5ef46e8eb26ab181
+ image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
+ images_picker: f01be5684149ad15ee37b5f270a3d50fdb33afa5
+ just_audio: 6c031bb61297cf218b4462be616638e81c058e97
+ libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009
+ nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
+ package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
+ path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
+ permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
+ PINCache: d9a87a0ff397acffe9e2f0db972ac14680441158
+ PINOperation: fb563bcc9c32c26d6c78aaff967d405aa2ee74a7
+ PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
+ PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
+ SDWebImage: 73c6079366fea25fa4bb9640d5fb58f0893facd8
+ share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
+ shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
+ sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
+ SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
+ url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
+ video_compress: f2133a07762889d67f0711ac831faa26f956980e
+ video_player_avfoundation: 2cef49524dd1f16c5300b9cd6efd9611ce03639b
+ video_thumbnail: b637e0ad5f588ca9945f6e2c927f73a69a661140
+ wakelock_plus: 04623e3f525556020ebd4034310f20fe7fda8b49
+ webview_flutter_wkwebview: 44d4dee7d7056d5ad185d25b38404436d56c547c
+ ZLPhotoBrowser: 4bfab86b851042e18d7f413284472aa68759626a
-PODFILE CHECKSUM: 56099e53bf102df458f588dbe78632cd13d5357b
+PODFILE CHECKSUM: c47b194cb97680e602c9d704f278cff245139eb7
-COCOAPODS: 1.11.2
+COCOAPODS: 1.16.2
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 65bc1088..2ba6889e 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -3,12 +3,21 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 51;
+ objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
- 1B77A5C027A5C39000510271 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 1B77A5BF27A5C39000510271 /* GoogleService-Info.plist */; };
+ 1B07DB412ABAD91A004AFB4E /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B07DB402ABAD90F004AFB4E /* libsqlite3.tbd */; };
+ 1B07DB422ABAD91A004AFB4E /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B07DB402ABAD90F004AFB4E /* libsqlite3.tbd */; };
+ 1B24F3CC282EC1F600256625 /* VideoEncoderSizes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B24F3CB282EC1F600256625 /* VideoEncoderSizes.swift */; };
+ 1B24F3CF282EC27300256625 /* EncoderBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B24F3CE282EC27300256625 /* EncoderBridge.swift */; };
+ 1B6A5097281E206800480755 /* AcelaWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B6A5096281E206800480755 /* AcelaWebViewController.swift */; };
+ 1B6A509E281E219E00480755 /* public in Resources */ = {isa = PBXBuildFile; fileRef = 1B6A509D281E219E00480755 /* public */; };
+ 1B6A50A1281E290300480755 /* AuthBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B6A50A0281E290300480755 /* AuthBridge.swift */; };
+ 1B6A50A4281F5AEF00480755 /* ValidateHiveKeyResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B6A50A3281F5AEF00480755 /* ValidateHiveKeyResponse.swift */; };
+ 1B951A4D2954716D00BBA4CF /* HASBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B951A4C2954716D00BBA4CF /* HASBridge.swift */; };
+ 1BBABA1B27E2F977000ABB58 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 1BBABA1A27E2F977000ABB58 /* GoogleService-Info.plist */; };
23F3017383FF2D45A9FFE1B2 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 900CC1210BBABA2901A394FB /* Pods_Runner.framework */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
@@ -33,7 +42,16 @@
/* Begin PBXFileReference section */
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 = ""; };
- 1B77A5BF27A5C39000510271 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };
+ 1B07DB402ABAD90F004AFB4E /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
+ 1B24F3CB282EC1F600256625 /* VideoEncoderSizes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoEncoderSizes.swift; sourceTree = ""; };
+ 1B24F3CE282EC27300256625 /* EncoderBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncoderBridge.swift; sourceTree = ""; };
+ 1B6A5096281E206800480755 /* AcelaWebViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AcelaWebViewController.swift; sourceTree = ""; };
+ 1B6A509D281E219E00480755 /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = ""; };
+ 1B6A50A0281E290300480755 /* AuthBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthBridge.swift; sourceTree = ""; };
+ 1B6A50A3281F5AEF00480755 /* ValidateHiveKeyResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValidateHiveKeyResponse.swift; sourceTree = ""; };
+ 1B951A4C2954716D00BBA4CF /* HASBridge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HASBridge.swift; sourceTree = ""; };
+ 1BBABA1A27E2F977000ABB58 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };
+ 1BFFAA0B285824800093D01C /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; };
3655DA9EF6F21F87FCBD0D8C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
571EA836831FEA283EA2C84D /* 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 = ""; };
@@ -56,6 +74,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 1B07DB422ABAD91A004AFB4E /* libsqlite3.tbd in Frameworks */,
+ 1B07DB412ABAD91A004AFB4E /* libsqlite3.tbd in Frameworks */,
23F3017383FF2D45A9FFE1B2 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -63,6 +83,41 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ 1B24F3CA282E8AF900256625 /* Encoder */ = {
+ isa = PBXGroup;
+ children = (
+ 1B24F3CB282EC1F600256625 /* VideoEncoderSizes.swift */,
+ );
+ path = Encoder;
+ sourceTree = "";
+ };
+ 1B24F3CD282EC26500256625 /* Encoder */ = {
+ isa = PBXGroup;
+ children = (
+ 1B24F3CE282EC27300256625 /* EncoderBridge.swift */,
+ );
+ path = Encoder;
+ sourceTree = "";
+ };
+ 1B6A509F281E28F600480755 /* Bridges */ = {
+ isa = PBXGroup;
+ children = (
+ 1B24F3CD282EC26500256625 /* Encoder */,
+ 1B6A50A2281F5AE500480755 /* Auth */,
+ );
+ path = Bridges;
+ sourceTree = "";
+ };
+ 1B6A50A2281F5AE500480755 /* Auth */ = {
+ isa = PBXGroup;
+ children = (
+ 1B951A4C2954716D00BBA4CF /* HASBridge.swift */,
+ 1B6A50A0281E290300480755 /* AuthBridge.swift */,
+ 1B6A50A3281F5AEF00480755 /* ValidateHiveKeyResponse.swift */,
+ );
+ path = Auth;
+ sourceTree = "";
+ };
2BD77FF19862F46541915B75 /* Pods */ = {
isa = PBXGroup;
children = (
@@ -76,6 +131,7 @@
5EF66C9F588A8934CC38BF1D /* Frameworks */ = {
isa = PBXGroup;
children = (
+ 1B07DB402ABAD90F004AFB4E /* libsqlite3.tbd */,
900CC1210BBABA2901A394FB /* Pods_Runner.framework */,
);
name = Frameworks;
@@ -114,6 +170,7 @@
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
+ 1BFFAA0B285824800093D01C /* Runner.entitlements */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
@@ -121,8 +178,12 @@
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
+ 1B24F3CA282E8AF900256625 /* Encoder */,
+ 1B6A509F281E28F600480755 /* Bridges */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
- 1B77A5BF27A5C39000510271 /* GoogleService-Info.plist */,
+ 1BBABA1A27E2F977000ABB58 /* GoogleService-Info.plist */,
+ 1B6A5096281E206800480755 /* AcelaWebViewController.swift */,
+ 1B6A509D281E219E00480755 /* public */,
);
path = Runner;
sourceTree = "";
@@ -142,6 +203,8 @@
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
214AAB41E8D0416E47EF2909 /* [CP] Embed Pods Frameworks */,
+ E16D86D96B9AC4CC871B1E93 /* [firebase_crashlytics] Crashlytics Upload Symbols */,
+ DDDD97A17EC4BBAA45BD69B0 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -158,7 +221,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1300;
+ LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@@ -192,7 +255,8 @@
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
- 1B77A5C027A5C39000510271 /* GoogleService-Info.plist in Resources */,
+ 1BBABA1B27E2F977000ABB58 /* GoogleService-Info.plist in Resources */,
+ 1B6A509E281E219E00480755 /* public in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
@@ -242,10 +306,12 @@
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
+ "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
@@ -256,6 +322,7 @@
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@@ -268,6 +335,46 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
+ DDDD97A17EC4BBAA45BD69B0 /* [CP] Copy Pods Resources */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
+ );
+ name = "[CP] Copy Pods Resources";
+ outputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+ E16D86D96B9AC4CC871B1E93 /* [firebase_crashlytics] Crashlytics Upload Symbols */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}\"",
+ "\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/\"",
+ "\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Info.plist\"",
+ "\"$(TARGET_BUILD_DIR)/$(EXECUTABLE_PATH)\"",
+ "\"$(PROJECT_DIR)/firebase_app_id_file.json\"",
+ );
+ name = "[firebase_crashlytics] Crashlytics Upload Symbols";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"$PODS_ROOT/FirebaseCrashlytics/upload-symbols\" --flutter-project \"$PROJECT_DIR/firebase_app_id_file.json\" ";
+ };
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -276,7 +383,13 @@
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
+ 1B24F3CC282EC1F600256625 /* VideoEncoderSizes.swift in Sources */,
+ 1B6A5097281E206800480755 /* AcelaWebViewController.swift in Sources */,
+ 1B951A4D2954716D00BBA4CF /* HASBridge.swift in Sources */,
+ 1B6A50A4281F5AEF00480755 /* ValidateHiveKeyResponse.swift in Sources */,
+ 1B6A50A1281E290300480755 /* AuthBridge.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
+ 1B24F3CF282EC27300256625 /* EncoderBridge.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -332,6 +445,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
+ CURRENT_PROJECT_VERSION = "${FLUTTER_BUILD_NUMBER}";
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -343,12 +457,15 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
+ MARKETING_VERSION = "${FLUTTER_BUILD_NAME}";
MTL_ENABLE_DEBUG_INFO = NO;
+ PRODUCT_BUNDLE_IDENTIFIER = com.example.acela;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
+ VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
@@ -357,17 +474,26 @@
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = "${FLUTTER_BUILD_NUMBER}";
DEVELOPMENT_TEAM = 58LRY57FMK;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = 3Speak.tv;
+ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.video";
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.3speak.Acela;
+ MARKETING_VERSION = "${FLUTTER_BUILD_NAME}";
+ PRODUCT_BUNDLE_IDENTIFIER = com.example.acela;
PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
@@ -404,6 +530,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
+ CURRENT_PROJECT_VERSION = "${FLUTTER_BUILD_NUMBER}";
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@@ -421,11 +548,14 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
+ MARKETING_VERSION = "${FLUTTER_BUILD_NAME}";
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = com.example.acela;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
+ VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
@@ -459,6 +589,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
+ CURRENT_PROJECT_VERSION = "${FLUTTER_BUILD_NUMBER}";
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -470,14 +601,17 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
+ MARKETING_VERSION = "${FLUTTER_BUILD_NAME}";
MTL_ENABLE_DEBUG_INFO = NO;
+ PRODUCT_BUNDLE_IDENTIFIER = com.example.acela;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
+ VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
@@ -486,17 +620,26 @@
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = "${FLUTTER_BUILD_NUMBER}";
DEVELOPMENT_TEAM = 58LRY57FMK;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = 3Speak.tv;
+ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.video";
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.3speak.Acela;
+ MARKETING_VERSION = "${FLUTTER_BUILD_NAME}";
+ PRODUCT_BUNDLE_IDENTIFIER = com.example.acela;
PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
@@ -509,17 +652,26 @@
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = "${FLUTTER_BUILD_NUMBER}";
DEVELOPMENT_TEAM = 58LRY57FMK;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = 3Speak.tv;
+ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.video";
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.3speak.Acela;
+ MARKETING_VERSION = "${FLUTTER_BUILD_NAME}";
+ PRODUCT_BUNDLE_IDENTIFIER = com.example.acela;
PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index c87d15a3..c53e2b31 100644
--- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
diff --git a/ios/Runner/AcelaWebViewController.swift b/ios/Runner/AcelaWebViewController.swift
new file mode 100644
index 00000000..fc1a8217
--- /dev/null
+++ b/ios/Runner/AcelaWebViewController.swift
@@ -0,0 +1,344 @@
+//
+// AcelaWebViewController.swift
+// Runner
+//
+// Created by Sagar on 01/05/22.
+//
+
+import UIKit
+import WebKit
+
+class AcelaWebViewController: UIViewController {
+ let acela = "acela"
+ let config = WKWebViewConfiguration()
+ let rect = CGRect(x: 0, y: 0, width: 10, height: 10)
+ var webView: WKWebView?
+ var didFinish = false
+ var postingKeyValidationHandler: ((String) -> Void)?
+ var decryptTokenHandler: ((String) -> Void)?
+ var postVideoHandler: ((String) -> Void)?
+ var postPodcastHandler: ((String) -> Void)?
+
+ var getRedirectUriHandler: ((String) -> Void)? = nil
+ var getRedirectUriDataHandler: ((String) -> Void)? = nil
+ var hiveUserInfoHandler: ((String) -> Void)? = nil
+ var getDecryptedHASTokenHandler: ((String) -> Void)? = nil
+ var voteContentHandler: ((String) -> Void)? = nil
+ var commentOnContentHandler: ((String) -> Void)? = nil
+ var getHtmlHandler: ((String) -> Void)? = nil
+ var getProofOfPayloadHandler: ((String) -> Void)? = nil
+ var getEncryptedChallengeHandler: ((String) -> Void)? = nil
+ var getDecryptedChallengeHandler: ((String) -> Void)? = nil
+ var doWeHavePostingAuthHandler: ((String) -> Void)? = nil
+ var getAccountInfoHandler: ((String) -> Void)? = nil
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ config.userContentController.add(self, name: acela)
+ webView = WKWebView(frame: rect, configuration: config)
+ webView?.navigationDelegate = self
+ guard
+ let url = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "public")
+ else { return }
+ let dir = url.deletingLastPathComponent()
+ webView?.loadFileURL(url, allowingReadAccessTo: dir)
+//#if DEBUG
+ if #available(iOS 16.4, *) {
+ self.webView?.isInspectable = true
+ }
+//#endif
+ }
+
+ func getHtml(string: String, handler: @escaping (String) -> Void) {
+ getHtmlHandler = handler
+ OperationQueue.main.addOperation {
+ self.webView?.evaluateJavaScript("getHTMLStringForContent('\(string)');")
+ }
+ }
+
+ func validatePostingKey(
+ username: String,
+ postingKey: String,
+ handler: @escaping (String) -> Void
+ ) {
+ postingKeyValidationHandler = handler
+ OperationQueue.main.addOperation {
+ self.webView?.evaluateJavaScript("validateHiveKey('\(username)', '\(postingKey)');")
+ }
+ }
+
+ func decryptMemo(
+ username: String,
+ postingKey: String,
+ encryptedMemo: String,
+ handler: @escaping (String) -> Void
+ ) {
+ decryptTokenHandler = handler
+ OperationQueue.main.addOperation {
+ self.webView?.evaluateJavaScript("decryptMemo('\(username)', '\(postingKey)', '\(encryptedMemo)');")
+ }
+ }
+
+ func voteContent(
+ user: String,
+ author: String,
+ permlink: String,
+ weight: Double,
+ postingKey: String,
+ hasKey: String,
+ hasAuthKey: String,
+ handler: @escaping (String) -> Void
+ ) {
+ voteContentHandler = handler
+ OperationQueue.main.addOperation {
+ self.webView?.evaluateJavaScript("voteContent('\(user)', '\(author)', '\(permlink)', \(weight), '\(postingKey)', '\(hasKey)', '\(hasAuthKey)');")
+ }
+ }
+
+ func commentOnContent(
+ user: String,
+ author: String,
+ permlink: String,
+ comment: String,
+ postingKey: String,
+ hasKey: String,
+ hasAuthKey: String,
+ handler: @escaping (String) -> Void
+ ) {
+ commentOnContentHandler = handler
+ OperationQueue.main.addOperation {
+ self.webView?.evaluateJavaScript("commentOnContent('\(user)', '\(author)', '\(permlink)', '\(comment)', '\(postingKey)', '\(hasKey)', '\(hasAuthKey)');")
+ }
+ }
+
+ func postVideo(
+ thumbnail: String,
+ video_v2: String,
+ description: String,
+ title: String,
+ tags: String,
+ username: String,
+ permlink: String,
+ duration: Double,
+ size: Double,
+ originalFilename: String,
+ firstUpload: Bool,
+ bene: String,
+ beneW: String,
+ postingKey: String,
+ community: String,
+ ipfsHash: String,
+ hasKey: String,
+ hasAuthkey: String,
+ newBene: String,
+ language: String,
+ powerUp: Bool,
+ handler: @escaping (String) -> Void
+ ) {
+ postVideoHandler = handler
+ OperationQueue.main.addOperation {
+ self.webView?.evaluateJavaScript("newPostVideo('\(thumbnail)','\(video_v2)', '\(description)', '\(title)', '\(tags)', '\(username)', '\(permlink)', \(duration), \(size), '\(originalFilename)', '\(language)', \(firstUpload ? "true" : "false"), '\(bene)', '\(beneW)', '\(postingKey)', '\(community)', '\(ipfsHash)', '\(hasKey)', '\(hasAuthkey)', '\(newBene)', \(powerUp ? "true" : "false"));")
+ }
+ }
+
+ func getProofOfPayload(username: String, password: String, proof: String, handler: @escaping (String) -> Void) {
+ getProofOfPayloadHandler = handler
+ OperationQueue.main.addOperation {
+ self.webView?.evaluateJavaScript("getProofOfPayload('\(username)','\(password)', '\(proof)');")
+ }
+ }
+
+ func getEncryptedChallenge(username: String, authKey: String, handler: @escaping (String) -> Void) {
+ getEncryptedChallengeHandler = handler
+ OperationQueue.main.addOperation {
+ self.webView?.evaluateJavaScript("getEncryptedChallenge('\(username)','\(authKey)');")
+ }
+ }
+
+ func getDecryptedChallenge(username: String, authKey: String, data: String, handler: @escaping (String) -> Void) {
+ getDecryptedChallengeHandler = handler
+ OperationQueue.main.addOperation {
+ self.webView?.evaluateJavaScript("getDecryptedChallenge('\(username)','\(authKey)', '\(data)');")
+ }
+ }
+
+ func doWeHavePostingAuth(username: String, handler: @escaping (String) -> Void) {
+ doWeHavePostingAuthHandler = handler
+ OperationQueue.main.addOperation {
+ self.webView?.evaluateJavaScript("doWeHavePostingAuth('\(username)');")
+ }
+ }
+
+ func getAccountInfo(username: String, handler: @escaping (String) -> Void) {
+ getAccountInfoHandler = handler
+ OperationQueue.main.addOperation {
+ self.webView?.evaluateJavaScript("getAccountInfo('\(username)');")
+ }
+ }
+
+ func postPodcast(
+ thumbnail: String,
+ enclosureUrl: String,
+ description: String,
+ title: String,
+ tags: String,
+ username: String,
+ permlink: String,
+ duration: Double,
+ size: Double,
+ originalFilename: String,
+ firstUpload: Bool,
+ bene: String,
+ beneW: String,
+ postingKey: String,
+ community: String,
+ ipfsHash: String,
+ hasKey: String,
+ hasAuthkey: String,
+ newBene: String,
+ language: String,
+ powerUp: Bool,
+ handler: @escaping (String) -> Void
+ ) {
+ postPodcastHandler = handler
+ OperationQueue.main.addOperation {
+ self.webView?.evaluateJavaScript("newPostPodcast('\(thumbnail)','\(enclosureUrl)', '\(description)', '\(title)', '\(tags)', '\(username)', '\(permlink)', \(duration), \(size), '\(originalFilename)', '\(language)', \(firstUpload ? "true" : "false"), '\(bene)', '\(beneW)', '\(postingKey)', '\(community)', '\(ipfsHash)', '\(hasKey)', '\(hasAuthkey)', '\(newBene)', \(powerUp ? "true" : "false"));")
+ }
+ }
+
+ func getRedirectUri(_ username: String, handler: @escaping (String) -> Void) {
+ getRedirectUriHandler = handler
+ webView?.evaluateJavaScript("getRedirectUri('\(username)');")
+ }
+
+ func getRedirectUriData(_ username: String, handler: @escaping (String) -> Void) {
+ getRedirectUriDataHandler = handler
+ webView?.evaluateJavaScript("getRedirectUriData('\(username)');")
+ }
+
+ func getDecryptedHASToken(
+ username: String,
+ authKey: String,
+ data: String,
+ handler: @escaping (String) -> Void
+ ) {
+ getDecryptedHASTokenHandler = handler
+ webView?.evaluateJavaScript("getDecryptedHASToken('\(username)','\(authKey)','\(data)');")
+ }
+
+ func getUserInfo(_ handler: @escaping (String) -> Void) {
+ hiveUserInfoHandler = handler
+ webView?.evaluateJavaScript("getUserInfo();")
+ }
+}
+
+extension AcelaWebViewController: WKNavigationDelegate {
+ func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
+ didFinish = true
+ }
+}
+
+extension AcelaWebViewController: WKScriptMessageHandler {
+ func userContentController(
+ _ userContentController: WKUserContentController,
+ didReceive message: WKScriptMessage
+ ) {
+ guard message.name == acela else { return }
+ guard let dict = message.body as? [String: AnyObject] else { return }
+ guard let type = dict["type"] as? String else { return }
+ switch type {
+ case "validateHiveKey":
+ guard
+ let response = ValidateHiveKeyResponse.jsonStringFrom(dict: dict)
+ else { return }
+ postingKeyValidationHandler?(response)
+ case "decryptedMemo":
+ guard
+ let accountName = dict["accountName"] as? String,
+ let error = dict["error"] as? String,
+ let decrypted = dict["decrypted"] as? String,
+ let response = DecryptMemoResponse.jsonStringFrom(dict: dict)
+ else { return }
+ debugPrint("account name is \(accountName)")
+ debugPrint("Error is \(error)")
+ debugPrint("decrypted is \(decrypted)")
+ decryptTokenHandler?(response)
+ case "postVideo":
+ guard
+ let isValid = dict["valid"] as? Bool,
+ let error = dict["error"] as? String,
+ let response = ValidateHiveKeyResponse.jsonStringFrom(dict: dict)
+ else { return }
+ debugPrint("Is it valid? \(isValid ? "TRUE" : "FALSE")")
+ debugPrint("Error is \(error)")
+ postVideoHandler?(response)
+ case "postAudio":
+ guard
+ let response = ValidateHiveKeyResponse.jsonStringFrom(dict: dict)
+ else { return }
+ postPodcastHandler?(response)
+ case "hiveAuthUserInfo":
+ guard
+ let response = ValidateHiveKeyResponse.jsonStringFrom(dict: dict)
+ else { return }
+ hiveUserInfoHandler?(response)
+ case "getRedirectUri":
+ guard
+ let response = ValidateHiveKeyResponse.jsonStringFrom(dict: dict)
+ else { return }
+ getRedirectUriHandler?(response)
+ case "getRedirectUriData":
+ guard
+ let response = ValidateHiveKeyResponse.jsonStringFrom(dict: dict)
+ else { return }
+ getRedirectUriDataHandler?(response)
+ case "getDecryptedHASToken":
+ guard
+ let response = ValidateHiveKeyResponse.jsonStringFrom(dict: dict)
+ else { return }
+ getDecryptedHASTokenHandler?(response)
+ case "voteContent":
+ guard
+ let response = ValidateHiveKeyResponse.jsonStringFrom(dict: dict)
+ else { return }
+ voteContentHandler?(response)
+ case "commentOnContent":
+ guard
+ let response = ValidateHiveKeyResponse.jsonStringFrom(dict: dict)
+ else { return }
+ commentOnContentHandler?(response)
+ case "getHTMLStringForContent":
+ guard
+ let response = ValidateHiveKeyResponse.jsonStringFrom(dict: dict)
+ else { return }
+ getHtmlHandler?(response)
+ case "getProofOfPayload":
+ guard
+ let response = ValidateHiveKeyResponse.jsonStringFrom(dict: dict)
+ else { return }
+ getProofOfPayloadHandler?(response)
+ case "getEncryptedChallenge":
+ guard
+ let response = ValidateHiveKeyResponse.jsonStringFrom(dict: dict)
+ else { return }
+ getEncryptedChallengeHandler?(response)
+ case "getDecryptedChallenge":
+ guard
+ let response = ValidateHiveKeyResponse.jsonStringFrom(dict: dict)
+ else { return }
+ getDecryptedChallengeHandler?(response)
+ case "getAccountInfo":
+ guard
+ let data = try? JSONSerialization.data(withJSONObject: dict),
+ let string = String(data: data, encoding: .utf8)
+ else { return }
+ getAccountInfoHandler?(string)
+ case "doWeHavePostingAuth":
+ guard
+ let response = ValidateHiveKeyResponse.jsonStringFrom(dict: dict)
+ else { return }
+ doWeHavePostingAuthHandler?(response)
+ default: debugPrint("Do nothing here.")
+ }
+ }
+}
diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift
index 70693e4a..1d990d06 100644
--- a/ios/Runner/AppDelegate.swift
+++ b/ios/Runner/AppDelegate.swift
@@ -1,13 +1,41 @@
import UIKit
import Flutter
+import AVKit
+import flutter_downloader
-@UIApplicationMain
+@main
@objc class AppDelegate: FlutterAppDelegate {
- override func application(
- _ application: UIApplication,
- didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
- ) -> Bool {
- GeneratedPluginRegistrant.register(with: self)
- return super.application(application, didFinishLaunchingWithOptions: launchOptions)
- }
+ var acela: AcelaWebViewController?
+ let authBridge = AuthBridge()
+ let encoderBridge = EncoderBridge()
+ let hasBridge = HASBridge()
+
+ override func application(
+ _ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
+ ) -> Bool {
+ acela = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "AcelaWebViewController") as? AcelaWebViewController
+
+ acela?.viewDidLoad()
+
+ let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
+ authBridge.initiate(controller: controller, window: window, acela: acela)
+ encoderBridge.initiate(controller: controller, window: window, acela: acela)
+ hasBridge.initiate(controller: controller, window: window, acela: acela)
+
+ GeneratedPluginRegistrant.register(with: self)
+ FlutterDownloaderPlugin.setPluginRegistrantCallback({ registry in
+ if (!registry.hasPlugin("FlutterDownloaderPlugin")) {
+ FlutterDownloaderPlugin.register(with: registry.registrar(forPlugin: "FlutterDownloaderPlugin")!)
+ }
+ })
+
+ return super.application(application, didFinishLaunchingWithOptions: launchOptions)
+ }
+
+// override func applicationDidBecomeActive(_ application: UIApplication) {
+// if (TSSocket.shared.tusClient == nil) {
+// TSSocket.shared.connect()
+// }
+// }
}
diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard
index f3c28516..0f0a8a10 100644
--- a/ios/Runner/Base.lproj/Main.storyboard
+++ b/ios/Runner/Base.lproj/Main.storyboard
@@ -1,8 +1,11 @@
-
-
+
+
+
-
+
+
+
@@ -14,13 +17,37 @@
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ios/Runner/Bridges/Auth/AuthBridge.swift b/ios/Runner/Bridges/Auth/AuthBridge.swift
new file mode 100644
index 00000000..6e071e18
--- /dev/null
+++ b/ios/Runner/Bridges/Auth/AuthBridge.swift
@@ -0,0 +1,291 @@
+//
+// AuthBridge.swift
+// Runner
+//
+// Created by Sagar on 01/05/22.
+//
+
+import UIKit
+import Flutter
+import AVFoundation
+import AVKit
+
+class AuthBridge {
+ var window: UIWindow?
+ var acela: AcelaWebViewController?
+
+ func initiate(controller: FlutterViewController, window: UIWindow?, acela: AcelaWebViewController?) {
+ self.window = window
+ self.acela = acela
+ let authChannel = FlutterMethodChannel(
+ name: "com.example.acela/auth",
+ binaryMessenger: controller.binaryMessenger
+ )
+ authChannel.setMethodCallHandler({
+ [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
+ // Note: this method is invoked on the UI thread.
+ switch (call.method) {
+ case "playFullscreen":
+ guard
+ let arguments = call.arguments as? NSDictionary,
+ let stringUrl = arguments ["url"] as? String,
+ let seconds = arguments ["seconds"] as? Int,
+ let url = URL(string: stringUrl)
+ else {
+ result(FlutterMethodNotImplemented)
+ return
+ }
+ let myTime = CMTime(seconds: Double(seconds), preferredTimescale: 60000)
+ let controller = AVPlayerViewController()
+ let player = AVPlayer(url: url)
+ controller.player = player
+ player.seek(to: myTime, toleranceBefore: .zero, toleranceAfter: .zero)
+ player.play()
+ window?.rootViewController?.present(controller, animated: true)
+ result("done")
+ case "getHTMLStringForContent":
+ guard
+ let arguments = call.arguments as? NSDictionary,
+ let string = arguments ["string"] as? String
+ else {
+ result(FlutterMethodNotImplemented)
+ return
+ }
+ self?.getHtml(string: string, result: result)
+ case "validateHiveKey":
+ guard
+ let arguments = call.arguments as? NSDictionary,
+ let username = arguments ["username"] as? String,
+ let password = arguments["postingKey"] as? String
+ else {
+ result(FlutterMethodNotImplemented)
+ return
+ }
+ self?.authenticate(username: username, postingKey: password, result: result)
+ case "encryptedToken":
+ guard
+ let arguments = call.arguments as? NSDictionary,
+ let username = arguments ["username"] as? String,
+ let password = arguments["postingKey"] as? String,
+ let encryptedToken = arguments["encryptedToken"] as? String
+ else {
+ result(FlutterMethodNotImplemented)
+ return
+ }
+ self?.decryptMemo(username: username, postingKey: password, encryptedMemo: encryptedToken, result: result)
+ case "getProofOfPayload":
+ guard
+ let arguments = call.arguments as? NSDictionary,
+ let username = arguments ["username"] as? String,
+ let password = arguments["postingKey"] as? String,
+ let proof = arguments["proof"] as? String,
+ let acela = acela
+ else {
+ result(FlutterMethodNotImplemented)
+ return
+ }
+ acela.getProofOfPayload(username: username, password: password, proof: proof) { data in
+ result(data)
+ }
+ case "newPostPodcast":
+ guard
+ let arguments = call.arguments as? NSDictionary,
+ let thumbnail = arguments["thumbnail"] as? String,
+ let enclosureUrl = arguments["enclosureUrl"] as? String,
+ let description = arguments["description"] as? String,
+ let title = arguments["title"] as? String,
+ let tags = arguments["tags"] as? String,
+ let username = arguments["username"] as? String,
+ let permlink = arguments["permlink"] as? String,
+ let duration = arguments["duration"] as? Double,
+ let size = arguments["size"] as? Double,
+ let originalFilename = arguments["originalFilename"] as? String,
+ let firstUpload = arguments["firstUpload"] as? Bool,
+ let bene = arguments["bene"] as? String,
+ let beneW = arguments["beneW"] as? String,
+ let postingKey = arguments["postingKey"] as? String,
+ let community = arguments["community"] as? String,
+ let ipfsHash = arguments["ipfsHash"] as? String,
+ let hasKey = arguments["hasKey"] as? String,
+ let hasAuthKey = arguments["hasAuthKey"] as? String,
+ let newBene = arguments["newBene"] as? String,
+ let language = arguments["language"] as? String,
+ let powerUp = arguments["powerUp"] as? Bool,
+ let acela = acela
+ else {
+ result(FlutterMethodNotImplemented)
+ return
+ }
+ acela.postPodcast(
+ thumbnail: thumbnail,
+ enclosureUrl: enclosureUrl,
+ description: description,
+ title: title,
+ tags: tags,
+ username: username,
+ permlink: permlink,
+ duration: duration,
+ size: size,
+ originalFilename: originalFilename,
+ firstUpload: firstUpload,
+ bene: bene,
+ beneW: beneW,
+ postingKey: postingKey,
+ community: community,
+ ipfsHash: ipfsHash,
+ hasKey: hasKey,
+ hasAuthkey: hasAuthKey,
+ newBene: newBene,
+ language: language,
+ powerUp: powerUp
+ ) { response in
+ result(response)
+ }
+ case "newPostVideo":
+ guard
+ let arguments = call.arguments as? NSDictionary,
+ let thumbnail = arguments["thumbnail"] as? String,
+ let video_v2 = arguments["video_v2"] as? String,
+ let description = arguments["description"] as? String,
+ let title = arguments["title"] as? String,
+ let tags = arguments["tags"] as? String,
+ let username = arguments["username"] as? String,
+ let permlink = arguments["permlink"] as? String,
+ let duration = arguments["duration"] as? Double,
+ let size = arguments["size"] as? Double,
+ let originalFilename = arguments["originalFilename"] as? String,
+ let firstUpload = arguments["firstUpload"] as? Bool,
+ let bene = arguments["bene"] as? String,
+ let beneW = arguments["beneW"] as? String,
+ let postingKey = arguments["postingKey"] as? String,
+ let community = arguments["community"] as? String,
+ let ipfsHash = arguments["ipfsHash"] as? String,
+ let hasKey = arguments["hasKey"] as? String,
+ let hasAuthKey = arguments["hasAuthKey"] as? String,
+ let newBene = arguments["newBene"] as? String,
+ let language = arguments["language"] as? String,
+ let powerUp = arguments["powerUp"] as? Bool,
+ let acela = acela
+ else {
+ result(FlutterMethodNotImplemented)
+ return
+ }
+ acela.postVideo(
+ thumbnail: thumbnail,
+ video_v2: video_v2,
+ description: description,
+ title: title,
+ tags: tags,
+ username: username,
+ permlink: permlink,
+ duration: duration,
+ size: size,
+ originalFilename: originalFilename,
+ firstUpload: firstUpload,
+ bene: bene,
+ beneW: beneW,
+ postingKey: postingKey,
+ community: community,
+ ipfsHash: ipfsHash,
+ hasKey: hasKey,
+ hasAuthkey: hasAuthKey,
+ newBene: newBene,
+ language: language,
+ powerUp: powerUp
+ ) { response in
+ result(response)
+ }
+ case "voteContent":
+ guard
+ let arguments = call.arguments as? NSDictionary,
+ let user = arguments["user"] as? String,
+ let author = arguments["author"] as? String,
+ let permlink = arguments["permlink"] as? String,
+ let weight = arguments["weight"] as? Double,
+ let postingKey = arguments["postingKey"] as? String,
+ let hasKey = arguments["hasKey"] as? String,
+ let hasAuthKey = arguments["hasAuthKey"] as? String,
+ let acela = acela
+ else {
+ result(FlutterMethodNotImplemented)
+ return
+ }
+ acela.voteContent(user: user, author: author, permlink: permlink, weight: weight, postingKey: postingKey, hasKey: hasKey, hasAuthKey: hasAuthKey) { response in
+ result(response)
+ }
+ case "commentOnContent":
+ guard
+ let arguments = call.arguments as? NSDictionary,
+ let user = arguments["user"] as? String,
+ let author = arguments["author"] as? String,
+ let permlink = arguments["permlink"] as? String,
+ let comment = arguments["comment"] as? String,
+ let postingKey = arguments["postingKey"] as? String,
+ let hasKey = arguments["hasKey"] as? String,
+ let hasAuthKey = arguments["hasAuthKey"] as? String,
+ let acela = acela
+ else {
+ result(FlutterMethodNotImplemented)
+ return
+ }
+ acela.commentOnContent(user: user, author: author, permlink: permlink, comment: comment, postingKey: postingKey, hasKey: hasKey, hasAuthKey: hasAuthKey) { response in
+ result(response)
+ }
+ case "getAccountInfo":
+ guard
+ let arguments = call.arguments as? NSDictionary,
+ let username = arguments["username"] as? String,
+ let acela = acela
+ else {
+ result(FlutterMethodNotImplemented)
+ return
+ }
+ acela.getAccountInfo(username: username) { response in
+ result(response)
+ }
+ default: debugPrint("do nothing")
+ }
+ })
+ }
+
+ private func getHtml(string: String, result: @escaping FlutterResult) {
+ guard let acela = acela else {
+ result(FlutterError(code: "ERROR",
+ message: "Error setting up Hive",
+ details: nil))
+ return
+ }
+ acela.getHtml(string: string) { response in
+ result(response)
+ }
+ }
+
+ private func authenticate(username: String, postingKey: String, result: @escaping FlutterResult) {
+ guard let acela = acela else {
+ result(FlutterError(code: "ERROR",
+ message: "Error setting up Hive",
+ details: nil))
+ return
+ }
+ acela.validatePostingKey(username: username, postingKey: postingKey) { response in
+ result(response)
+ }
+ }
+
+ private func decryptMemo(
+ username: String,
+ postingKey: String,
+ encryptedMemo: String,
+ result: @escaping FlutterResult
+ ) {
+ guard let acela = acela else {
+ result(FlutterError(code: "ERROR",
+ message: "Error setting up Hive",
+ details: nil))
+ return
+ }
+ acela.decryptMemo(username: username, postingKey: postingKey, encryptedMemo: encryptedMemo) { response in
+ result(response)
+ }
+ }
+}
diff --git a/ios/Runner/Bridges/Auth/HASBridge.swift b/ios/Runner/Bridges/Auth/HASBridge.swift
new file mode 100644
index 00000000..fb1db024
--- /dev/null
+++ b/ios/Runner/Bridges/Auth/HASBridge.swift
@@ -0,0 +1,156 @@
+//
+// Bridge.swift
+// Runner
+//
+// Created by Sagar on 24/11/22.
+//
+
+import Foundation
+import UIKit
+import Flutter
+
+class HASBridge {
+ var window: UIWindow?
+ var acela: AcelaWebViewController?
+
+ func initiate(
+ controller: FlutterViewController,
+ window: UIWindow?,
+ acela: AcelaWebViewController?
+ ) {
+ self.window = window
+ self.acela = acela
+ let authChannel = FlutterMethodChannel(
+ name: "blog.hive.auth/bridge",
+ binaryMessenger: controller.binaryMessenger
+ )
+
+ authChannel.setMethodCallHandler({
+ [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
+ // Note: this method is invoked on the UI thread.
+ switch (call.method) {
+ case "getRedirectUri":
+ guard
+ let arguments = call.arguments as? NSDictionary,
+ let username = arguments ["username"] as? String
+ else {
+ result(FlutterMethodNotImplemented)
+ return
+ }
+ self?.getRedirectUri(username: username, result: result)
+ case "getRedirectUriData":
+ guard
+ let arguments = call.arguments as? NSDictionary,
+ let username = arguments ["username"] as? String
+ else {
+ result(FlutterMethodNotImplemented)
+ return
+ }
+ self?.getRedirectUriData(username: username, result: result)
+ case "getDecryptedHASToken":
+ guard
+ let arguments = call.arguments as? NSDictionary,
+ let username = arguments ["username"] as? String,
+ let authKey = arguments ["authKey"] as? String,
+ let data = arguments ["data"] as? String
+ else {
+ result(FlutterMethodNotImplemented)
+ return
+ }
+ self?.getDecryptedHASToken(username: username, authKey: authKey, data: data, result: result)
+ case "getUserInfo":
+ self?.getUserInfo(result: result)
+ case "getEncryptedChallenge":
+ guard
+ let arguments = call.arguments as? NSDictionary,
+ let username = arguments ["username"] as? String,
+ let authKey = arguments["authKey"] as? String,
+ let acela = acela
+ else {
+ result(FlutterMethodNotImplemented)
+ return
+ }
+ acela.getEncryptedChallenge(username: username, authKey: authKey) { data in
+ result(data)
+ }
+ case "getDecryptedChallenge":
+ guard
+ let arguments = call.arguments as? NSDictionary,
+ let username = arguments ["username"] as? String,
+ let authKey = arguments["authKey"] as? String,
+ let data = arguments["data"] as? String,
+ let acela = acela
+ else {
+ result(FlutterMethodNotImplemented)
+ return
+ }
+ acela.getDecryptedChallenge(username: username, authKey: authKey, data: data) { data in
+ result(data)
+ }
+ case "doWeHavePostingAuth":
+ guard
+ let arguments = call.arguments as? NSDictionary,
+ let username = arguments ["username"] as? String,
+ let acela = acela
+ else {
+ result(FlutterMethodNotImplemented)
+ return
+ }
+ acela.doWeHavePostingAuth(username: username) { data in
+ result(data)
+ }
+ default:
+ result(FlutterMethodNotImplemented)
+ }
+ })
+ }
+
+ private func getDecryptedHASToken(username: String, authKey: String, data: String, result: @escaping FlutterResult) {
+ guard let acela = acela else {
+ result(FlutterError(code: "ERROR",
+ message: "Error setting up Hive",
+ details: nil))
+ return
+ }
+ acela.getDecryptedHASToken(username: username, authKey: authKey, data: data) { string in
+ result(string)
+ }
+ }
+
+ private func getUserInfo(result: @escaping FlutterResult) {
+ guard let acela = acela else {
+ result(FlutterError(code: "ERROR",
+ message: "Error setting up Hive",
+ details: nil))
+ return
+ }
+ acela.getUserInfo { string in
+ result(string)
+ }
+ }
+
+ private func getRedirectUri(username: String, result: @escaping FlutterResult) {
+ guard let acela = acela else {
+ result(FlutterError(code: "ERROR",
+ message: "Error setting up Hive",
+ details: nil))
+ return
+ }
+ acela.getRedirectUri(username) { string in
+ result(string)
+ }
+ }
+
+ private func getRedirectUriData(username: String, result: @escaping FlutterResult) {
+ guard let acela = acela else {
+ result(FlutterError(code: "ERROR",
+ message: "Error setting up Hive",
+ details: nil))
+ return
+ }
+ acela.getRedirectUriData(username) { string in
+ debugPrint("Sending string back - \(string)")
+ result(string)
+ }
+ }
+}
diff --git a/ios/Runner/Bridges/Auth/ValidateHiveKeyResponse.swift b/ios/Runner/Bridges/Auth/ValidateHiveKeyResponse.swift
new file mode 100644
index 00000000..bc4364fc
--- /dev/null
+++ b/ios/Runner/Bridges/Auth/ValidateHiveKeyResponse.swift
@@ -0,0 +1,76 @@
+//
+// ValidateHiveKeyResponse.swift
+// Runner
+//
+// Created by Sagar on 02/05/22.
+//
+
+import Foundation
+
+struct ValidateHiveKeyResponse: Codable {
+ let valid: Bool
+ let accountName: String?
+ let error: String
+ let data: String?
+
+ static func jsonStringFrom(dict: [String: AnyObject]) -> String? {
+ guard
+ let isValid = dict["valid"] as? Bool,
+ let error = dict["error"] as? String
+ else { return nil }
+ let response = ValidateHiveKeyResponse(
+ valid: isValid,
+ accountName: dict["accountName"] as? String,
+ error: error,
+ data: dict["data"] as? String
+ )
+ guard
+ let data = try? JSONEncoder().encode(response)
+ else { return nil }
+ guard
+ let dataString = String(data: data, encoding: .utf8)
+ else { return nil }
+ return dataString
+ }
+}
+
+struct DecryptMemoResponse: Codable {
+ let accountName: String
+ let decrypted: String
+ let error: String
+
+ static func jsonStringFrom(dict: [String: AnyObject]) -> String? {
+ guard
+ let accountName = dict["accountName"] as? String,
+ let error = dict["error"] as? String,
+ let decrypted = dict["decrypted"] as? String
+ else { return nil }
+ let response = DecryptMemoResponse(
+ accountName: accountName,
+ decrypted: decrypted,
+ error: error
+ )
+ guard let data = try? JSONEncoder().encode(response) else { return nil }
+ guard let dataString = String(data: data, encoding: .utf8) else { return nil }
+ return dataString
+ }
+}
+
+struct PostVideoResponse: Codable {
+ let valid: Bool
+ let error: String
+
+ static func jsonStringFrom(dict: [String: AnyObject]) -> String? {
+ guard
+ let valid = dict["valid"] as? Bool,
+ let error = dict["error"] as? String
+ else { return nil }
+ let response = PostVideoResponse(
+ valid: valid,
+ error: error
+ )
+ guard let data = try? JSONEncoder().encode(response) else { return nil }
+ guard let dataString = String(data: data, encoding: .utf8) else { return nil }
+ return dataString
+ }
+}
diff --git a/ios/Runner/Bridges/Encoder/EncoderBridge.swift b/ios/Runner/Bridges/Encoder/EncoderBridge.swift
new file mode 100644
index 00000000..36fa29e4
--- /dev/null
+++ b/ios/Runner/Bridges/Encoder/EncoderBridge.swift
@@ -0,0 +1,192 @@
+//
+// EncoderBridge.swift
+// Runner
+//
+// Created by Sagar on 13/05/22.
+//
+
+import Foundation
+import UIKit
+import Flutter
+import PhotosUI
+import FYVideoCompressor
+import MobileCoreServices
+
+class EncoderBridge: NSObject {
+ var window: UIWindow?
+ var acela: AcelaWebViewController?
+ var controller: FlutterViewController?
+ let picker = UIImagePickerController()
+ var result: FlutterResult?
+
+ func initiate(controller: FlutterViewController, window: UIWindow?, acela: AcelaWebViewController?) {
+ self.window = window
+ self.acela = acela
+ self.controller = controller
+ let encoderChannel = FlutterMethodChannel(
+ name: "com.example.acela/encoder",
+ binaryMessenger: controller.binaryMessenger
+ )
+ encoderChannel.setMethodCallHandler({
+ [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
+ // Note: this method is invoked on the UI thread.
+ guard
+ call.method == "video",
+ let arguments = call.arguments as? NSDictionary,
+ let username = arguments ["username"] as? String,
+ let password = arguments["postingKey"] as? String
+ else {
+ result(FlutterMethodNotImplemented)
+ return
+ }
+ self?.video(username: username, postingKey: password, result: result)
+ })
+ }
+
+ private func video(username: String, postingKey: String, result: @escaping FlutterResult) {
+ guard let acela = acela else {
+ result(FlutterError(code: "ERROR",
+ message: "Error setting up Hive",
+ details: nil))
+ return
+ }
+ acela.validatePostingKey(username: username, postingKey: postingKey) { [weak self] response in
+ guard
+ let data = response.data(using: .utf8),
+ let object = try? JSONDecoder().decode(ValidateHiveKeyResponse.self, from: data),
+ object.valid == true
+ else {
+ result(response)
+ return
+ }
+ self?.showPicker(result: result)
+ }
+ }
+
+ func showPicker(result: @escaping FlutterResult) {
+ if #available(iOS 14, *) {
+ PHPhotoLibrary.requestAuthorization(for: .readWrite) { (status) in
+ DispatchQueue.main.async {
+ self.showUI(for: status, result: result)
+ }
+ }
+ } else {
+ showVideoPicker(result: result)
+ }
+ }
+
+ func showUI(for status: PHAuthorizationStatus, result: @escaping FlutterResult) {
+ switch status {
+ case .authorized:
+ showVideoPicker(result: result)
+ case .limited:
+ showVideoPicker(result: result)
+ case .restricted:
+ showVideoPicker(result: result)
+ case .denied:
+ result(FlutterError(code: "ERROR",
+ message: "Please provide access. Go to Settings > Acela > Photos > Selected Photos / All Photos",
+ details: nil))
+ case .notDetermined:
+ result(FlutterError(code: "ERROR",
+ message: "Please provide access. Go to Settings > Acela > Photos > Selected Photos / All Photos.",
+ details: nil))
+ break
+ @unknown default:
+ break
+ }
+ }
+
+ func showVideoPicker(result: @escaping FlutterResult) {
+ if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
+ picker.sourceType = .photoLibrary
+ picker.mediaTypes = ["public.movie"]
+ picker.allowsEditing = false
+ picker.delegate = self
+ controller?.present(picker, animated: true, completion: nil)
+ self.result = result
+ } else {
+ result(FlutterError(code: "ERROR",
+ message: "Please provide access. Go to Settings > Acela > Photos > Selected Photos / All Photos.",
+ details: nil))
+ }
+ }
+
+ func convertToMP4(url: URL) {
+ let fm = FileManager.default
+ var comps = url.lastPathComponent.components(separatedBy: CharacterSet(charactersIn: "."))
+ comps.removeLast()
+ let fileName = comps.joined(separator: ".")
+ let docDir = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
+ let docDirFilePath = "\(docDir)/\(fileName).mp4"
+ try? fm.removeItem(atPath: docDirFilePath)
+ let docDirFileUrl = URL(fileURLWithPath: docDirFilePath)
+ let asset = AVURLAsset(url: url)
+ let export = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetPassthrough)
+ export?.outputURL = docDirFileUrl
+ export?.outputFileType = AVFileType.mp4
+ export?.exportAsynchronously(completionHandler: {
+ debugPrint("DocDir url - \(docDirFileUrl.absoluteString)")
+ let asset = AVAsset(url: docDirFileUrl)
+ let duration = asset.duration
+ let durationTime = CMTimeGetSeconds(duration)
+ debugPrint("Video duration is in seconds - \(durationTime) seconds")
+ do {
+ let attr = try FileManager.default.attributesOfItem(atPath: docDirFilePath)
+ let fileSize = attr[FileAttributeKey.size] as! UInt64
+ debugPrint("Video file size is - \(fileSize)")
+ let responseString = VideoDataResponse.jsonStringFrom(size: Int(fileSize), duration: Int(durationTime), oFilename: "\(fileName).mp4", path: docDirFileUrl.absoluteString)
+ self.result?(responseString)
+ } catch {
+ print("Error: \(error)")
+ }
+ })
+ }
+}
+
+struct VideoDataResponse: Codable {
+ let size: Int
+ let duration: Int
+ let oFilename: String
+ let path: String
+
+ static func jsonStringFrom(size: Int, duration: Int, oFilename: String, path: String) -> String? {
+ let response = VideoDataResponse(
+ size: size,
+ duration: duration,
+ oFilename: oFilename,
+ path: path
+ )
+ guard let data = try? JSONEncoder().encode(response) else { return nil }
+ guard let dataString = String(data: data, encoding: .utf8) else { return nil }
+ return dataString
+ }
+}
+
+extension EncoderBridge: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
+ func imagePickerController(
+ _ picker: UIImagePickerController,
+ didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]
+ ) {
+ if let type = info[UIImagePickerController.InfoKey.mediaType] as? String,
+ type == kUTTypeMovie as String,
+ let url = info[UIImagePickerController.InfoKey.mediaURL] as? URL {
+ picker.dismiss(animated: true) {
+ debugPrint("URL of media is \(url.debugDescription)")
+ self.convertToMP4(url: url)
+ }
+ } else {
+ picker.dismiss(animated: true, completion: nil)
+ result?(FlutterError(code: "ERROR",
+ message: "Selection of media is not a video.",
+ details: nil))
+ }
+ }
+
+ func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
+ picker.dismiss(animated: true, completion: nil)
+ result?(FlutterError(code: "ERROR",
+ message: "You cancelled selection of videos.",
+ details: nil))
+ }
+}
diff --git a/ios/Runner/Encoder/VideoEncoderSizes.swift b/ios/Runner/Encoder/VideoEncoderSizes.swift
new file mode 100644
index 00000000..ab66c696
--- /dev/null
+++ b/ios/Runner/Encoder/VideoEncoderSizes.swift
@@ -0,0 +1,123 @@
+//
+// VideoEncoderSizes.swift
+// Runner
+//
+// Created by Sagar on 13/05/22.
+//
+
+import UIKit
+import MobileCoreServices
+import AVFoundation
+import FYVideoCompressor
+
+// 240p, 480p, 720p, 1080p, 1440p, 2160p
+enum VideoQuality {
+ case veryLow
+ case low
+ case medium
+ case high
+ case twoK
+ case fourK
+
+ var size: CGSize {
+ switch self {
+ case .veryLow: return CGSize(width: 240, height: 0)
+ case .low: return CGSize(width: 480, height: 0)
+ case .medium: return CGSize(width: 720, height: 0)
+ case .high: return CGSize(width: 1080, height: 0)
+ case .twoK: return CGSize(width: 1440, height: 0)
+ case .fourK: return CGSize(width: 2160, height: 0)
+ }
+ }
+
+ var stringValue: String {
+ switch self {
+ case .veryLow: return "veryLow"
+ case .low: return "low"
+ case .medium: return "medium"
+ case .high: return "high"
+ case .twoK: return "2K"
+ case .fourK: return "4K"
+ }
+ }
+
+ var intValue: Int {
+ switch self {
+ case .veryLow: return 0
+ case .low: return 1
+ case .medium: return 2
+ case .high: return 3
+ case .twoK: return 4
+ case .fourK: return 5
+ }
+ }
+
+ static func from(_ intValue: Int) -> VideoQuality {
+ switch intValue {
+ case 0: return .veryLow
+ case 1: return .low
+ case 2: return .medium
+ case 3: return .high
+ case 4: return .twoK
+ default: return .low
+ }
+ }
+
+ var bitrate: Int {
+ switch self {
+ case .veryLow: return 1000_000 // 1 mbps
+ case .low: return 1250_000 // 1.25 mbps
+ case .medium: return 5000_000 // 5 mbps
+ case .high: return 8000_000 // 8 mbps
+ case .twoK: return 16000_000 // 16 mbps
+ case .fourK: return 35000_000 // 35 mbps
+ }
+ }
+
+ var framerate: Float {
+ switch self {
+ case .veryLow: return 15
+ case .low: return 17
+ case .medium: return 22
+ case .high: return 24
+ case .twoK: return 25
+ case .fourK: return 26
+ }
+ }
+
+ var config: FYVideoCompressor.CompressionConfig {
+ FYVideoCompressor.CompressionConfig(
+ videoBitrate: bitrate,
+ videomaxKeyFrameInterval: 10,
+ fps: framerate,
+ audioSampleRate: 44100,
+ audioBitrate: 128_000,
+ fileType: .mp4,
+ scale: size)
+ }
+}
+
+public extension URL {
+ var fileSize: Int? {
+ let value = try? resourceValues(forKeys: [.fileSizeKey])
+ return value?.fileSize
+ }
+
+ var getThumbnail: UIImage? {
+ do {
+ let asset = AVURLAsset(url: self)
+ let imageGenerator = AVAssetImageGenerator(asset: asset)
+ imageGenerator.appliesPreferredTrackTransform = true
+
+ // Swift 5.3
+ let cgImage = try imageGenerator.copyCGImage(at: .zero,
+ actualTime: nil)
+
+ return UIImage(cgImage: cgImage)
+ } catch {
+ print(error.localizedDescription)
+
+ return nil
+ }
+ }
+}
diff --git a/ios/Runner/GoogleService-Info.plist b/ios/Runner/GoogleService-Info.plist
index c0e7a352..c35d3307 100644
--- a/ios/Runner/GoogleService-Info.plist
+++ b/ios/Runner/GoogleService-Info.plist
@@ -3,9 +3,9 @@
CLIENT_ID
- 252548198943-m20qel1pq01m3p8ivhfg9ac54600j8cg.apps.googleusercontent.com
+ 252548198943-ec3gnethnkvoudaat0lrobmq2t7mve8g.apps.googleusercontent.com
REVERSED_CLIENT_ID
- com.googleusercontent.apps.252548198943-m20qel1pq01m3p8ivhfg9ac54600j8cg
+ com.googleusercontent.apps.252548198943-ec3gnethnkvoudaat0lrobmq2t7mve8g
API_KEY
AIzaSyBhRRZgrQb8WfCKVMjOwC4jnK0XiMuK4YM
GCM_SENDER_ID
@@ -13,7 +13,7 @@
PLIST_VERSION
1
BUNDLE_ID
- com.3speak.Acela
+ com.example.acela
PROJECT_ID
acela-9c624
STORAGE_BUCKET
@@ -29,6 +29,6 @@
IS_SIGNIN_ENABLED
GOOGLE_APP_ID
- 1:252548198943:ios:de180e80d89dc46e355b2a
+ 1:252548198943:ios:2fcda030e33a7164355b2a
\ No newline at end of file
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index cffa1ab8..f107805f 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -1,52 +1,78 @@
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleDisplayName
- Acela
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- acela
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- $(FLUTTER_BUILD_NAME)
- CFBundleSignature
- ????
- CFBundleVersion
- $(FLUTTER_BUILD_NUMBER)
- LSRequiresIPhoneOS
-
- NSAppTransportSecurity
-
- NSAllowsArbitraryLoads
-
-
- UILaunchStoryboardName
- LaunchScreen
- UIMainStoryboardFile
- Main
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UISupportedInterfaceOrientations~ipad
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UIViewControllerBasedStatusBarAppearance
-
-
+
+ CADisableMinimumFrameDurationOnPhone
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ 3Speak
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ 3Speak
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ $(FLUTTER_BUILD_NAME)
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ $(FLUTTER_BUILD_NUMBER)
+ ITSAppUsesNonExemptEncryption
+
+ LSRequiresIPhoneOS
+
+ LSSupportsOpeningDocumentsInPlace
+
+ NSAppTransportSecurity
+
+ NSAllowsArbitraryLoads
+
+
+ NSAppleMusicUsageDescription
+ Allow access to music
+ NSCameraUsageDescription
+ Allow access to camera to capture the video
+ NSMicrophoneUsageDescription
+ Allow access to microphone while capturing the video
+ NSPhotoLibraryUsageDescription
+ Allow access to videos
+ UIApplicationSupportsIndirectInputEvents
+
+ UIBackgroundModes
+
+ audio
+ fetch
+ remote-notification
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+
+ UISupportsDocumentBrowser
+
+ UIViewControllerBasedStatusBarAppearance
+
+ FDAllFilesDownloadedMessage
+ All files have been downloaded
+ FDMaximumConcurrentTasks
+ 5
+
diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements
new file mode 100644
index 00000000..903def2a
--- /dev/null
+++ b/ios/Runner/Runner.entitlements
@@ -0,0 +1,8 @@
+
+
+
+
+ aps-environment
+ development
+
+
diff --git a/ios/Runner/public/index.html b/ios/Runner/public/index.html
new file mode 100644
index 00000000..eec94027
--- /dev/null
+++ b/ios/Runner/public/index.html
@@ -0,0 +1,924 @@
+
+
+
+
+
+
+
+ 3Speak
+
+
+
+ You need to enable JavaScript to run this app.
+
+
+
+
+
+
+
+
+
diff --git a/ios/app.json b/ios/app.json
new file mode 100644
index 00000000..f6026b31
--- /dev/null
+++ b/ios/app.json
@@ -0,0 +1,44 @@
+{
+ "name": "3Speak - Acela Source",
+ "identifier": "com.example.acela",
+ "sourceURL": "https://github.com/spknetwork/Android-App/raw/development/ios/app.json",
+ "apps": [
+ {
+ "name": "3Speak.tv - Acela",
+ "bundleIdentifier": "com.example.acela",
+ "developerName": "sagarkothari88",
+ "subtitle": "Tokenized Video Communities",
+ "version": "1.0.3",
+ "versionDate": "2022-12-08",
+ "versionDescription": "https://ecency.com/hive-181335/@sagarkothari88/3speak-development-update-from-sagarkothari88-7cd51a3b88448",
+ "downloadURL": "https://github.com/spknetwork/Android-App/releases/download/v1.0.3_48/Runner.ipa",
+ "localizedDescription": "The build which was also submitted to the Apple for TestFlight review",
+ "iconURL": "https://github.com/spknetwork/Android-App/releases/download/v1.0.3_48/AppIcon-512.png",
+ "tintColor": "AFEEEE",
+ "size": 857669,
+ "permissions": [
+ ],
+ "screenshotURLs": [
+ "https://github.com/spknetwork/Android-App/releases/download/v1.0.3_48/IMG_5651.PNG",
+ "https://github.com/spknetwork/Android-App/releases/download/v1.0.3_48/IMG_5652.PNG",
+ "https://github.com/spknetwork/Android-App/releases/download/v1.0.3_48/IMG_5653.PNG",
+ "https://github.com/spknetwork/Android-App/releases/download/v1.0.3_48/IMG_5654.PNG",
+ "https://github.com/spknetwork/Android-App/releases/download/v1.0.3_48/IMG_5655.PNG"
+ ],
+ "beta": false
+ }
+ ],
+ "news": [
+ {
+ "title": "3Speak.tv Acela - Download now - via AltStore",
+ "identifier": "3speak-tv-acela-download-2022-12-08",
+ "caption": "3Speak.tv Acela release via AltStore",
+ "date": "2022-12-08",
+ "tintColor": "afeeee",
+ "imageURL": "https://github.com/spknetwork/Android-App/releases/download/v1.0.3_48/AppIcon-512.png",
+ "url": "https://ecency.com/hive-181335/@sagarkothari88/3speak-development-update-from-sagarkothari88-7cd51a3b88448",
+ "appID": "com.example.acela",
+ "notify": true
+ }
+ ]
+}
diff --git a/lib/generated_plugin_registrant.dart b/lib/generated_plugin_registrant.dart
index 7552fd6b..88732597 100644
--- a/lib/generated_plugin_registrant.dart
+++ b/lib/generated_plugin_registrant.dart
@@ -4,17 +4,26 @@
// ignore_for_file: directives_ordering
// ignore_for_file: lines_longer_than_80_chars
+// ignore_for_file: depend_on_referenced_packages
-import 'package:firebase_core_web/firebase_core_web.dart';
+import 'package:file_picker/_internal/file_picker_web.dart';
+import 'package:flutter_secure_storage_web/flutter_secure_storage_web.dart';
+import 'package:image_picker_for_web/image_picker_for_web.dart';
+import 'package:url_launcher_web/url_launcher_web.dart';
import 'package:video_player_web/video_player_web.dart';
import 'package:video_player_web_hls/video_player_web_hls.dart';
+import 'package:wakelock_web/wakelock_web.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
// ignore: public_member_api_docs
void registerPlugins(Registrar registrar) {
- FirebaseCoreWeb.registerWith(registrar);
+ FilePickerWeb.registerWith(registrar);
+ FlutterSecureStorageWeb.registerWith(registrar);
+ ImagePickerPlugin.registerWith(registrar);
+ UrlLauncherPlugin.registerWith(registrar);
VideoPlayerPlugin.registerWith(registrar);
VideoPlayerPluginHls.registerWith(registrar);
+ WakelockWeb.registerWith(registrar);
registrar.registerMessageHandler();
}
diff --git a/lib/main.dart b/lib/main.dart
index 77a47a90..e4dcd0fc 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,42 +1,226 @@
-import 'package:acela/src/screens/home_screen/home_screen.dart';
-import 'package:acela/src/screens/video_details_screen/video_details_screen.dart';
-import 'package:firebase_core/firebase_core.dart';
+import 'package:acela/src/bloc/server.dart';
+import 'package:acela/src/global_provider/image_resolution_provider.dart';
+import 'package:acela/src/global_provider/video_setting_provider.dart';
+import 'package:acela/src/models/user_stream/hive_user_stream.dart';
+import 'package:acela/src/screens/podcast/controller/podcast_controller.dart';
+import 'package:acela/src/screens/podcast/controller/podcast_player_controller.dart';
+import 'package:acela/src/screens/report/controller/report_controller.dart';
+import 'package:acela/src/screens/upload/video/controller/video_upload_controller.dart';
+import 'package:acela/src/utils/graphql/gql_communicator.dart';
+import 'package:acela/src/utils/routes/app_router.dart';
import 'package:flutter/material.dart';
+import 'package:flutter_dotenv/flutter_dotenv.dart';
+import 'package:flutter_secure_storage/flutter_secure_storage.dart';
+import 'package:get_storage/get_storage.dart';
+import 'package:overlay_support/overlay_support.dart';
+import 'package:provider/provider.dart';
+import 'dart:async';
+import 'package:flutter_downloader/flutter_downloader.dart';
+import 'package:audio_service/audio_service.dart';
+import 'package:upgrader/upgrader.dart';
+import 'src/screens/podcast/widgets/audio_player/audio_player_core_controls.dart';
Future main() async {
+ await dotenv.load(fileName: "dotenv");
WidgetsFlutterBinding.ensureInitialized();
- runApp(MyApp());
+ await GetStorage.init();
+ await FlutterDownloader.initialize(
+ debug: true,
+ ignoreSsl: true,
+ );
+ GetAudioPlayer getAudioPlayer = GetAudioPlayer();
+ getAudioPlayer.audioHandler = await AudioService.init(
+ builder: () => AudioPlayerHandlerImpl(),
+ config: const AudioServiceConfig(
+ androidNotificationChannelId: 'com.ryanheise.myapp.channel.audio',
+ androidNotificationChannelName: 'Audio playback',
+ androidNotificationOngoing: true,
+ ),
+ );
+ // await Upgrader.clearSavedSettings(); // for debugging
+ await Upgrader.sharedInstance.initialize();
+ runApp(const MyApp());
+
+}
+
+class MyApp extends StatefulWidget {
+ const MyApp({Key? key}) : super(key: key);
+
+ @override
+ _MyAppState createState() => _MyAppState();
}
-class MyApp extends StatelessWidget {
- final Future _fbApp = Firebase.initializeApp();
+class _MyAppState extends State {
+ late final Future _futureToLoadData;
Widget futureBuilder(Widget withWidget) {
return FutureBuilder(
- future: _fbApp,
- builder: (context, snapshot) {
- if (snapshot.hasError) {
- return const Text('Firebase not initialized');
- } else if (snapshot.hasData) {
- return withWidget;
- } else {
- return const CircularProgressIndicator();
- }
- });
+ future: _futureToLoadData,
+ builder: (context, snapshot) {
+ if (snapshot.hasError) {
+ return const Text('Firebase not initialized');
+ } else if (snapshot.connectionState == ConnectionState.done) {
+ return withWidget;
+ } else {
+ return MaterialApp(
+ title: '3Speak',
+ home: Scaffold(
+ appBar: AppBar(title: const Text('3Speak')),
+ body: const Center(
+ child: CircularProgressIndicator(),
+ ),
+ ),
+ );
+ }
+ },
+ );
}
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
- return MaterialApp(
- title: 'Acela - 3Speak App',
- theme: ThemeData.dark(),
- routes: {
- VideoDetailsScreen.routeName: (context) =>
- futureBuilder(const VideoDetailsScreen()),
- '/': (context) => futureBuilder(const HomeScreen()),
+ return MultiProvider(
+ providers: [
+ StreamProvider.value(
+ value: server.hiveUserData,
+ initialData: HiveUserData(
+ resolution: '480p',
+ keychainData: null,
+ accessToken: null,
+ postingKey: null,
+ username: null,
+ cookie: null,
+ postingAuthority: null,
+ rpc: 'api.hive.blog',
+ union: GQLCommunicator.defaultGQLServer,
+ loaded: false,
+ language: null,
+ ),),
+ ChangeNotifierProxyProvider(
+ lazy: false,
+ create: (_) => ReportController(),
+ update: (_, hiveUserData, reportController) {
+ reportController?.updateHiveUserData(hiveUserData);
+ return reportController!;
},
- // home: const HomeScreen(),
+ ),
+
+ ChangeNotifierProvider(
+ lazy: false,
+ create: (context) => PodcastController(),
+ ),
+ ChangeNotifierProvider(
+ lazy: false, create: (context) => VideoSettingProvider()),
+ ChangeNotifierProvider(
+ lazy: false,
+ create: (context) => SettingsProvider(),
+ ),
+ ChangeNotifierProvider(
+ create: (context) => PodcastPlayerController(),
+ ),
+ ChangeNotifierProxyProvider(
+ create: (_) => VideoUploadController(null),
+ update: (_, hiveUserData, videoUploadController)=> VideoUploadController(hiveUserData.username),
+ ),
+ ],
+ child: OverlaySupport.global(
+ child: futureBuilder(
+ StreamProvider.value(
+ value: server.theme,
+ initialData: true,
+ child: const AcelaApp(),
+ ),
+ ),
+
+ ),
+ );
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ _futureToLoadData = loadData();
+ }
+
+ Future loadData() async {
+ const storage = FlutterSecureStorage();
+ String? username = await storage.read(key: 'username');
+ String? postingKey = await storage.read(key: 'postingKey');
+ String? cookie = await storage.read(key: 'cookie');
+ String? accessToken = await storage.read(key: 'accessToken');
+ String? hasId = await storage.read(key: 'hasId');
+ String? hasExpiry = await storage.read(key: 'hasExpiry');
+ String? hasAuthKey = await storage.read(key: 'hasAuthKey');
+ String resolution = await storage.read(key: 'resolution') ?? '480p';
+ String rpc = await storage.read(key: 'rpc') ?? 'api.hive.blog';
+ String? postingAuth = await storage.read(key: 'postingAuth');
+ String union =
+ await storage.read(key: 'union') ?? GQLCommunicator.defaultGQLServer;
+ if (union == 'threespeak-union-graph-ql.sagarkothari88.one') {
+ await storage.write(
+ key: 'union', value: GQLCommunicator.defaultGQLServer);
+ union = GQLCommunicator.defaultGQLServer;
+ }
+ String? lang = await storage.read(key: 'lang');
+ server.updateHiveUserData(
+ HiveUserData(
+ username: username,
+ postingKey: postingKey,
+ keychainData: hasId != null &&
+ hasId.isNotEmpty &&
+ hasExpiry != null &&
+ hasExpiry.isNotEmpty &&
+ hasAuthKey != null &&
+ hasAuthKey.isNotEmpty
+ ? HiveKeychainData(
+ hasAuthKey: hasAuthKey,
+ hasExpiry: hasExpiry,
+ hasId: hasId,
+ )
+ : null,
+ cookie: cookie,
+ accessToken: accessToken,
+ postingAuthority: postingAuth,
+ resolution: resolution,
+ rpc: rpc,
+ union: union,
+ loaded: true,
+ language: lang,
+ ),
+ );
+ }
+}
+
+class AcelaApp extends StatelessWidget {
+ const AcelaApp({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ var isDarkMode = Provider.of(context);
+ return MaterialApp.router(
+ title: 'Acela - 3Speak App',
+ routerConfig: AppRouter.router,
+ theme: isDarkMode
+ ? ThemeData.dark().copyWith(
+ primaryColor: Colors.deepPurple,
+ primaryColorLight: Colors.white,
+ primaryColorDark: Colors.black,
+ scaffoldBackgroundColor: Colors.black,
+ cardTheme: CardTheme(
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.all(Radius.circular(4))),
+ color: Colors.grey.shade900),
+ )
+ : ThemeData.light().copyWith(
+ primaryColor: Colors.deepPurple,
+ primaryColorLight: Colors.black,
+ primaryColorDark: Colors.white,
+ cardTheme: CardTheme(
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.all(Radius.circular(4))),
+ color: Colors.grey.shade200),
+ ),
+ debugShowCheckedModeBanner: false,
);
}
}
diff --git a/lib/src/bloc/server.dart b/lib/src/bloc/server.dart
index 3658dbe0..765728ec 100644
--- a/lib/src/bloc/server.dart
+++ b/lib/src/bloc/server.dart
@@ -1,11 +1,44 @@
+import 'dart:async';
+
+import 'package:acela/src/models/user_stream/hive_user_stream.dart';
class Server {
final String domain = "https://3speak.tv";
+
String userOwnerThumb(String value) {
return "https://images.hive.blog/u/$value/avatar";
}
- final String hiveDomain = "https://api.hive.blog";
+ String userChannelCover(String value) {
+ return "https://img.3speakcontent.co/user/$value/cover.png";
+ }
+
+ String communityIcon(String value) {
+ return "https://images.hive.blog/u/$value/avatar?size=icon";
+ }
+
+ String resizedImage(String value) {
+ return "https://images.hive.blog/640x0/$value";
+ }
+
+ final _controller = StreamController();
+ final _hiveUserDataController = StreamController();
+
+ Stream get theme {
+ return _controller.stream;
+ }
+
+ Stream get hiveUserData {
+ return _hiveUserDataController.stream;
+ }
+
+ void changeTheme(bool value) async {
+ _controller.sink.add(!value);
+ }
+
+ void updateHiveUserData(HiveUserData data) {
+ _hiveUserDataController.sink.add(data);
+ }
}
-Server server = Server();
\ No newline at end of file
+Server server = Server();
diff --git a/lib/src/extensions/ui.dart b/lib/src/extensions/ui.dart
new file mode 100644
index 00000000..624c9f05
--- /dev/null
+++ b/lib/src/extensions/ui.dart
@@ -0,0 +1,84 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+
+extension UI on BuildContext {
+ PageRouteBuilder fadePageRoute(Widget screen) {
+ return PageRouteBuilder(
+ fullscreenDialog: false,
+ opaque: false,
+ barrierColor: Colors.black.withOpacity(0.9),
+ barrierDismissible: true,
+ transitionDuration: const Duration(milliseconds: 200),
+ reverseTransitionDuration: const Duration(milliseconds: 200),
+ pageBuilder: (BuildContext context, _, __) {
+ return screen;
+ },
+ transitionsBuilder: (context, animation, secondaryAnimation, child) {
+ return FadeTransition(
+ opacity: animation,
+ child: child,
+ );
+ },
+ );
+ }
+
+ void showSnackBar(String message) {
+ ScaffoldMessenger.of(this).hideCurrentSnackBar();
+ ScaffoldMessenger.of(this).showSnackBar(SnackBar(
+ content: Text(
+ message,
+ textAlign: TextAlign.center,
+ ),
+ duration: const Duration(seconds: 3),
+ ));
+ }
+
+ PopScope _loader(BuildContext context, bool canPop) {
+ return PopScope(
+ canPop: canPop,
+ child: MediaQuery.removeViewInsets(
+ removeLeft: true,
+ removeTop: true,
+ removeRight: true,
+ removeBottom: true,
+ context: context,
+ child: Container(
+ color: Colors.transparent,
+ alignment: Alignment.center,
+ child: ConstrainedBox(
+ constraints: BoxConstraints.tight(
+ const Size.fromRadius(60),
+ ),
+ child: Center(
+ child: CircularProgressIndicator(
+ color: Theme.of(context).primaryColor,
+ strokeWidth: 4,
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+
+ void showLoader({bool canPop = false}) {
+ showDialog(
+ context: this,
+ useRootNavigator: true,
+ barrierDismissible: false,
+ builder: (context) => _loader(context, canPop),
+ );
+ }
+
+ void hideLoader() {
+ Navigator.of(this).pop();
+ }
+
+ void copyToClipbaord(text, {String? successMessage}) {
+ Clipboard.setData(ClipboardData(text: text)).then((_) {
+ if (successMessage != null) {
+ showSnackBar(successMessage);
+ }
+ });
+ }
+}
diff --git a/lib/src/global_provider/image_resolution_provider.dart b/lib/src/global_provider/image_resolution_provider.dart
new file mode 100644
index 00000000..50379a20
--- /dev/null
+++ b/lib/src/global_provider/image_resolution_provider.dart
@@ -0,0 +1,56 @@
+import 'package:flutter/material.dart';
+import 'package:get_storage/get_storage.dart';
+
+class SettingsProvider extends ChangeNotifier {
+ late String _resolution;
+ late bool _autoPlayVideo;
+ String _resolutionKey = 'videoImageResolution';
+ String _autoPlayVideoKey = 'autoPlayVideo';
+ GetStorage _storage = GetStorage();
+
+ SettingsProvider() {
+ _init();
+ }
+
+ void _init() {
+ _resolution = _storage.read(_resolutionKey) ?? Resolution.r480;
+ _autoPlayVideo = _storage.read(_autoPlayVideoKey) ?? true;
+ }
+
+ set resolution(String newResolution) {
+ if (newResolution != _resolution) {
+ _resolution = newResolution;
+ _storage.write(_resolutionKey, newResolution);
+ notifyListeners();
+ }
+ }
+
+ String get resolution {
+ String resolutionString = _resolution.toString().replaceAll('r', '');
+ return resolutionString;
+ }
+
+ set autoPlayVideo(bool status) {
+ if (status != _autoPlayVideo) {
+ _autoPlayVideo = status;
+ _storage.write(_autoPlayVideoKey, status);
+ notifyListeners();
+ }
+ }
+
+ bool get autoPlayVideo {
+ return _autoPlayVideo;
+ }
+}
+
+class Resolution {
+ static String r360 = '360p';
+ static String r480 = '480p';
+ static String r720 = '720p';
+ static String r1080 = '1080p';
+
+ static removePFromResolution(String resolution) {
+ String actualResolution = resolution.replaceAll('p', '');
+ return actualResolution;
+ }
+}
diff --git a/lib/src/global_provider/ipfs_node_provider.dart b/lib/src/global_provider/ipfs_node_provider.dart
new file mode 100644
index 00000000..228b2475
--- /dev/null
+++ b/lib/src/global_provider/ipfs_node_provider.dart
@@ -0,0 +1,31 @@
+import 'package:get_storage/get_storage.dart';
+
+class IpfsNodeProvider{
+ String storageKey = 'ipfsNode';
+ late String nodeUrl;
+ GetStorage _storage = GetStorage();
+ String defaultIpfsNode = 'https://ipfs-3speak.b-cdn.net/ipfs/';
+
+static IpfsNodeProvider? _instance;
+ IpfsNodeProvider._();
+
+ static IpfsNodeProvider get instance {
+ _instance ??= IpfsNodeProvider._();
+ return _instance!;
+ }
+ IpfsNodeProvider() {
+ _init();
+ }
+
+ void _init() {
+ nodeUrl = _storage.read(storageKey) ?? defaultIpfsNode;
+ }
+
+ void changeIpfsNode(String newUrl) {
+ if (newUrl != nodeUrl) {
+ nodeUrl = newUrl;
+ _storage.write(storageKey, newUrl);
+ }
+ }
+}
+
diff --git a/lib/src/global_provider/video_setting_provider.dart b/lib/src/global_provider/video_setting_provider.dart
new file mode 100644
index 00000000..87f68de2
--- /dev/null
+++ b/lib/src/global_provider/video_setting_provider.dart
@@ -0,0 +1,10 @@
+import 'package:flutter/material.dart';
+
+class VideoSettingProvider extends ChangeNotifier {
+ bool isMuted = true;
+
+ void changeMuteStatus(bool value) {
+ isMuted = value;
+ notifyListeners();
+ }
+}
diff --git a/lib/src/models/action_response.dart b/lib/src/models/action_response.dart
new file mode 100644
index 00000000..b19286b1
--- /dev/null
+++ b/lib/src/models/action_response.dart
@@ -0,0 +1,28 @@
+import 'dart:convert';
+
+class ActionResponse {
+ final String? type;
+ final String data;
+ final bool valid;
+ final String error;
+
+ ActionResponse({
+ this.type,
+ required this.data,
+ required this.valid,
+ required this.error,
+ });
+
+ factory ActionResponse.fromJsonString(String string,) =>
+ ActionResponse.fromJson(json.decode(string),);
+
+ factory ActionResponse.fromJson(
+ Map json,) {
+ return ActionResponse(
+ type: json['type'] as String,
+ data: (json['data'] ),
+ valid: json['valid'] as bool,
+ error: json['error'] as String,
+ );
+ }
+}
diff --git a/lib/src/models/communities_models/request/communities_request_model.dart b/lib/src/models/communities_models/request/communities_request_model.dart
new file mode 100644
index 00000000..56bd9bf9
--- /dev/null
+++ b/lib/src/models/communities_models/request/communities_request_model.dart
@@ -0,0 +1,66 @@
+import 'dart:convert';
+
+import 'package:acela/src/utils/safe_convert.dart';
+
+class CommunitiesRequestModel {
+ final CommunitiesRequestParams params;
+
+ // 2.0
+ final String jsonrpc;
+
+ // bridge.list_communities
+ final String method;
+
+ // 1
+ final int id;
+
+ CommunitiesRequestModel({
+ required this.params,
+ this.jsonrpc = "2.0",
+ this.method = "bridge.list_communities",
+ this.id = 1,
+ });
+
+ factory CommunitiesRequestModel.fromJson(Map? json) =>
+ CommunitiesRequestModel(
+ params: CommunitiesRequestParams.fromJson(asMap(json, 'params')),
+ jsonrpc: asString(json, 'jsonrpc'),
+ method: asString(json, 'method'),
+ id: asInt(json, 'id'),
+ );
+
+ Map toJson() => {
+ 'params': params.toJson(),
+ 'jsonrpc': jsonrpc,
+ 'method': method,
+ 'id': id,
+ };
+
+ String toJsonString() => json.encode(toJson());
+}
+
+class CommunitiesRequestParams {
+ // 100
+ final int limit;
+ final String? query;
+
+ CommunitiesRequestParams({
+ this.limit = 100,
+ this.query,
+ });
+
+ factory CommunitiesRequestParams.fromJson(Map? json) =>
+ CommunitiesRequestParams(
+ limit: asInt(json, 'limit'),
+ );
+
+ Map toJson() {
+ Map map = {
+ 'limit': limit,
+ };
+ if (query != null && query!.isNotEmpty) {
+ map['query'] = query;
+ }
+ return map;
+ }
+}
diff --git a/lib/src/models/communities_models/request/community_details_request.dart b/lib/src/models/communities_models/request/community_details_request.dart
new file mode 100644
index 00000000..6a04b784
--- /dev/null
+++ b/lib/src/models/communities_models/request/community_details_request.dart
@@ -0,0 +1,75 @@
+import 'package:acela/src/utils/safe_convert.dart';
+import 'dart:convert';
+
+class CommunityDetailsRequest {
+ final CommunityDetailsRequestParams params;
+
+ // 2.0
+ final String jsonrpc;
+
+ // bridge.get_community
+ final String method;
+
+ // 1
+ final int id;
+
+ CommunityDetailsRequest({
+ required this.params,
+ this.jsonrpc = "",
+ this.method = "",
+ this.id = 0,
+ });
+
+ factory CommunityDetailsRequest.fromJson(Map? json) =>
+ CommunityDetailsRequest(
+ params: CommunityDetailsRequestParams.fromJson(asMap(json, 'params')),
+ jsonrpc: asString(json, 'jsonrpc'),
+ method: asString(json, 'method'),
+ id: asInt(json, 'id'),
+ );
+
+ factory CommunityDetailsRequest.forName(String name) {
+ return CommunityDetailsRequest(
+ params: CommunityDetailsRequestParams.forName(name),
+ jsonrpc: "2.0",
+ method: "bridge.get_community",
+ id: 1,
+ );
+ }
+
+ Map toJson() => {
+ 'params': params.toJson(),
+ 'jsonrpc': jsonrpc,
+ 'method': method,
+ 'id': id,
+ };
+
+ String toJsonString() => json.encode(toJson());
+}
+
+class CommunityDetailsRequestParams {
+ // hive-167922
+ final String name;
+
+ // sagarkothari88
+ final String observer;
+
+ CommunityDetailsRequestParams({
+ this.name = "",
+ this.observer = "",
+ });
+
+ factory CommunityDetailsRequestParams.fromJson(Map? json) =>
+ CommunityDetailsRequestParams(
+ name: asString(json, 'name'),
+ observer: asString(json, 'observer'),
+ );
+
+ factory CommunityDetailsRequestParams.forName(String name) =>
+ CommunityDetailsRequestParams(name: name, observer: 'sagarkothari88');
+
+ Map toJson() => {
+ 'name': name,
+ 'observer': observer,
+ };
+}
diff --git a/lib/src/models/communities_models/response/communities_response_models.dart b/lib/src/models/communities_models/response/communities_response_models.dart
new file mode 100644
index 00000000..02a506f2
--- /dev/null
+++ b/lib/src/models/communities_models/response/communities_response_models.dart
@@ -0,0 +1,96 @@
+import 'dart:convert';
+
+import 'package:acela/src/utils/safe_convert.dart';
+
+CommunitiesResponseModel communitiesResponseModelFromString(String string) {
+ return CommunitiesResponseModel.fromJson(json.decode(string));
+}
+
+class CommunitiesResponseModel {
+ // 2.0
+ final String jsonrpc;
+ final List result;
+ // 1
+ final int id;
+
+ CommunitiesResponseModel({
+ this.jsonrpc = "",
+ required this.result,
+ this.id = 0,
+ });
+
+ factory CommunitiesResponseModel.fromJson(Map? json) =>
+ CommunitiesResponseModel(
+ jsonrpc: asString(json, 'jsonrpc'),
+ result: asList(json, 'result')
+ .map((e) => CommunityItem.fromJson(e))
+ .toList(),
+ id: asInt(json, 'id'),
+ );
+
+ Map toJson() => {
+ 'jsonrpc': jsonrpc,
+ 'result': result.map((e) => e.toJson()),
+ 'id': id,
+ };
+}
+
+class CommunityItem {
+ // 1341662
+ final int id;
+ // hive-167922
+ final String name;
+ // LeoFinance
+ final String title;
+ // LeoFinance is a community for crypto & finance. Powered by Hive and the LEO token economy.
+ final String about;
+ // 1
+ final int typeId;
+ // false
+ final bool isNsfw;
+ // 11475
+ final int subscribers;
+ // 29860
+ final int sumPending;
+ final int numAuthors;
+ final List admins;
+
+ CommunityItem({
+ this.id = 0,
+ this.name = "",
+ this.title = "",
+ this.about = "",
+ this.typeId = 0,
+ this.isNsfw = false,
+ this.subscribers = 0,
+ this.sumPending = 0,
+ this.numAuthors = 0,
+ required this.admins,
+ });
+
+ factory CommunityItem.fromJson(Map? json) => CommunityItem(
+ id: asInt(json, 'id'),
+ name: asString(json, 'name'),
+ title: asString(json, 'title'),
+ about: asString(json, 'about'),
+ typeId: asInt(json, 'type_id'),
+ isNsfw: asBool(json, 'is_nsfw'),
+ subscribers: asInt(json, 'subscribers'),
+ sumPending: asInt(json, 'sum_pending'),
+ numAuthors: asInt(json, 'num_authors'),
+ admins: asList(json, 'admins').map((e) => e.toString()).toList(),
+ );
+
+ Map toJson() => {
+ 'id': id,
+ 'name': name,
+ 'title': title,
+ 'about': about,
+ 'type_id': typeId,
+ 'is_nsfw': isNsfw,
+ 'subscribers': subscribers,
+ 'sum_pending': sumPending,
+ 'num_authors': numAuthors,
+ 'admins': admins.map((e) => e),
+ };
+}
diff --git a/lib/src/models/communities_models/response/community_details_response_models.dart b/lib/src/models/communities_models/response/community_details_response_models.dart
new file mode 100644
index 00000000..1fcddcdd
--- /dev/null
+++ b/lib/src/models/communities_models/response/community_details_response_models.dart
@@ -0,0 +1,142 @@
+import 'dart:developer';
+
+import 'package:acela/src/utils/safe_convert.dart';
+import 'dart:convert';
+
+class CommunityDetailsResponse {
+ // 2.0
+ final String jsonrpc;
+ final CommunityDetailsResponseResult result;
+
+ // 1
+ final int id;
+
+ CommunityDetailsResponse({
+ this.jsonrpc = "",
+ required this.result,
+ this.id = 0,
+ });
+
+ factory CommunityDetailsResponse.fromJson(Map? json) =>
+ CommunityDetailsResponse(
+ jsonrpc: asString(json, 'jsonrpc'),
+ result: CommunityDetailsResponseResult.fromJson(asMap(json, 'result')),
+ id: asInt(json, 'id'),
+ );
+
+ factory CommunityDetailsResponse.fromString(String string) =>
+ CommunityDetailsResponse.fromJson(json.decode(string));
+
+ Map toJson() => {
+ 'jsonrpc': jsonrpc,
+ 'result': result.toJson(),
+ 'id': id,
+ };
+}
+
+class CommunityDetailsResponseResult {
+ // 1341662
+ final int id;
+
+ // hive-167922
+ final String name;
+
+ // LeoFinance
+ final String title;
+
+ // LeoFinance is a community for crypto & finance. Powered by Hive and the LEO token economy.
+ final String about;
+
+ // en
+ final String lang;
+
+ // 1
+ final int typeId;
+
+ // false
+ final bool isNsfw;
+
+ // 12009
+ final int subscribers;
+
+ // 2019-11-26 17:25:27
+ final String createdAt;
+
+ // 22177
+ final int sumPending;
+
+ // 12112
+ final int numPending;
+
+ // 1435
+ final int numAuthors;
+ final String avatarUrl;
+
+ // Using our Hive-based token (LEO) we reward content creators and users for engaging on our platform at https://leofinance.io and within our community on the Hive blockchain. Blogging is just the beginning of what's possible in the LeoFinance community and with the LEO token:1). Trade LEO and other Hive-based tokens on our exchange: https://leodex.io2). Track your Hive account statistics at https://hivestats.io3). Opt-in to ads on LEO Apps which drives value back into the LEO token economy from ad buybacks.4). Learn & contribute to our crypto-educational resource at https://leopedia.io5). Wrap LEO onto the Ethereum blockchain with our cross-chain token bridge: https://wleo.io (coming soon)Learn more about us at https://leopedia.io/faq
+ final String description;
+
+ // Content should be related to the financial space (i.e. crypto, equities, etc. etc.)Posts created from our interface (https://leofinance.io) are eligible for upvotes from @leo.voter and will automatically be posted to our Hive community, our front end and other Hive front ends as wellPosts in our community are also eligible to earn our native token (LEO) in conjunction with HIVE post rewardsIf you have any questions or need help with anything, feel free to reach out to us on twitter (@financeleo) or head over to our discord server (https://discord.gg/KgcVDKQ)
+ final String flagText;
+ final List> team;
+
+ CommunityDetailsResponseResult({
+ this.id = 0,
+ this.name = "",
+ this.title = "",
+ this.about = "",
+ this.lang = "",
+ this.typeId = 0,
+ this.isNsfw = false,
+ this.subscribers = 0,
+ this.createdAt = "",
+ this.sumPending = 0,
+ this.numPending = 0,
+ this.numAuthors = 0,
+ this.avatarUrl = "",
+ this.description = "",
+ this.flagText = "",
+ required this.team,
+ });
+
+ factory CommunityDetailsResponseResult.fromJson(Map? json) =>
+ CommunityDetailsResponseResult(
+ id: asInt(json, 'id'),
+ name: asString(json, 'name'),
+ title: asString(json, 'title'),
+ about: asString(json, 'about'),
+ lang: asString(json, 'lang'),
+ typeId: asInt(json, 'type_id'),
+ isNsfw: asBool(json, 'is_nsfw'),
+ subscribers: asInt(json, 'subscribers'),
+ createdAt: asString(json, 'created_at'),
+ sumPending: asInt(json, 'sum_pending'),
+ numPending: asInt(json, 'num_pending'),
+ numAuthors: asInt(json, 'num_authors'),
+ avatarUrl: asString(json, 'avatar_url'),
+ description: asString(json, 'description'),
+ flagText: asString(json, 'flag_text'),
+ team: asList(json, 'team').map((e) {
+ log("Console message goes here");
+ return (e as List).map((s) => asDynamicString(s)).toList();
+ }).toList(),
+ );
+
+ Map toJson() => {
+ 'id': id,
+ 'name': name,
+ 'title': title,
+ 'about': about,
+ 'lang': lang,
+ 'type_id': typeId,
+ 'is_nsfw': isNsfw,
+ 'subscribers': subscribers,
+ 'created_at': createdAt,
+ 'sum_pending': sumPending,
+ 'num_pending': numPending,
+ 'num_authors': numAuthors,
+ 'avatar_url': avatarUrl,
+ 'description': description,
+ 'flag_text': flagText,
+ 'team': team.map((e) => e),
+ };
+}
diff --git a/lib/src/models/hive_comments/new_hive_comment/new_hive_comment.dart b/lib/src/models/hive_comments/new_hive_comment/new_hive_comment.dart
new file mode 100644
index 00000000..4d7c292f
--- /dev/null
+++ b/lib/src/models/hive_comments/new_hive_comment/new_hive_comment.dart
@@ -0,0 +1,136 @@
+import 'dart:convert';
+
+import 'package:equatable/equatable.dart';
+
+class GQLHiveCommentReponse {
+ final GQLHiveCommentReponseData data;
+
+ GQLHiveCommentReponse({
+ required this.data,
+ });
+
+ factory GQLHiveCommentReponse.fromRawJson(String str) =>
+ GQLHiveCommentReponse.fromJson(json.decode(str));
+
+ factory GQLHiveCommentReponse.fromJson(Map json) =>
+ GQLHiveCommentReponse(
+ data: GQLHiveCommentReponseData.fromJson(json["data"]),
+ );
+}
+
+class GQLHiveCommentReponseData {
+ final CommentSocialPostModel socialPost;
+
+ GQLHiveCommentReponseData({
+ required this.socialPost,
+ });
+
+ factory GQLHiveCommentReponseData.fromJson(Map json) => GQLHiveCommentReponseData(
+ socialPost: CommentSocialPostModel.fromJson(json["socialPost"]),
+ );
+}
+
+class CommentSocialPostModel {
+ final List? children;
+ final String? body;
+
+ CommentSocialPostModel({
+ required this.children,
+ required this.body,
+ });
+
+ factory CommentSocialPostModel.fromJson(Map json) => CommentSocialPostModel(
+ children:json["children"]!=null ? List.from(
+ json["children"].map((x) {
+ if(x!=null){
+ return VideoCommentModel.fromJson(x);
+ }
+ })) : [],
+ body: json["body"],
+ );
+}
+
+class VideoCommentModel extends Equatable{
+ final String? body;
+ final String permlink;
+ final DateTime? createdAt;
+ final VideoCommentAuthorModel author;
+ final VideoCommentStatsModel? stats;
+ final List? children;
+
+ VideoCommentModel({
+ required this.body,
+ required this.permlink,
+ required this.createdAt,
+ required this.author,
+ required this.stats,
+ required this.children,
+ });
+
+ VideoCommentModel copyWith({
+ int? numVotes,
+
+ }) {
+ return VideoCommentModel(
+ body: body,
+ permlink: permlink,
+ author: author,
+ children: children,
+ createdAt: createdAt,
+ stats: stats!.copyWith(numVotes : numVotes),
+ );
+ }
+
+ factory VideoCommentModel.fromJson(Map json) => VideoCommentModel(
+ body: json["body"],
+ permlink: json["permlink"],
+ createdAt: DateTime.parse(json["created_at"]),
+ author: VideoCommentAuthorModel.fromJson(json["author"]),
+ stats: VideoCommentStatsModel.fromJson(json["stats"]),
+ children:json["children"]!=null ? List.from(json["children"].map((x) {
+ if (x != null) {
+ return VideoCommentModel.fromJson(x);
+ }
+ })) : [],
+ );
+
+ @override
+ List get props => [body,permlink,createdAt,author,stats,children];
+}
+
+class VideoCommentAuthorModel {
+ final String username;
+
+ VideoCommentAuthorModel({
+ required this.username,
+ });
+
+ factory VideoCommentAuthorModel.fromJson(Map json) => VideoCommentAuthorModel(
+ username: json["username"],
+ );
+
+}
+
+class VideoCommentStatsModel extends Equatable{
+ final int? numVotes;
+
+ VideoCommentStatsModel({
+ required this.numVotes,
+ });
+
+ factory VideoCommentStatsModel.fromJson(Map? json) => VideoCommentStatsModel(
+ numVotes: json!=null ? json["num_votes"] ?? 0 : 0,
+ );
+
+ VideoCommentStatsModel copyWith({
+ int? numVotes,
+
+ }) {
+ return VideoCommentStatsModel(
+ numVotes: numVotes ?? this.numVotes
+ );
+ }
+
+ @override
+ List get props => [numVotes];
+}
diff --git a/lib/src/models/hive_comments/new_hive_comment/newest_comment_model.dart b/lib/src/models/hive_comments/new_hive_comment/newest_comment_model.dart
new file mode 100644
index 00000000..0b6664b3
--- /dev/null
+++ b/lib/src/models/hive_comments/new_hive_comment/newest_comment_model.dart
@@ -0,0 +1,400 @@
+import 'dart:convert';
+
+import 'package:equatable/equatable.dart';
+
+class CommentResponseModel {
+ final String? jsonrpc;
+ final List comments;
+ final int? id;
+
+ CommentResponseModel({
+ this.jsonrpc,
+ this.comments = const [],
+ this.id,
+ });
+
+ factory CommentResponseModel.fromRawJson(String str) =>
+ CommentResponseModel.fromJson(json.decode(str));
+
+ factory CommentResponseModel.fromJson(Map json) =>
+ CommentResponseModel(
+ jsonrpc: json["jsonrpc"],
+ comments: _parseComments(json["result"]),
+ id: json["id"],
+ );
+
+ static List _parseComments(Map? json) {
+ List items = [];
+ if (json != null) {
+ int count = 0;
+ json.forEach((key, value) {
+ if (count != 0) {
+ items.add(CommentItemModel.fromJson(value));
+ }
+ count++;
+ });
+ ;
+ }
+ return items;
+ }
+}
+
+// ignore: must_be_immutable
+class CommentItemModel extends Equatable {
+ final int? postId;
+ final String author;
+ final String permlink;
+ final String? category;
+ final String? title;
+ final String body;
+ final CommentMetaDataModel? jsonMetadata;
+ final DateTime created;
+ final DateTime? updated;
+ final int depth;
+ final int children;
+ final int? netRshares;
+ final bool? isPaidout;
+ final DateTime? payoutAt;
+ final double? payout;
+ final String? pendingPayoutValue;
+ final String? authorPayoutValue;
+ final String? curatorPayoutValue;
+ final String? promoted;
+ final List replies;
+ final int? reblogs;
+ final double? authorReputation;
+ final Stats? stats;
+ final String? url;
+ final List? beneficiaries;
+ final String? maxAcceptedPayout;
+ final int? percentHbd;
+ final String? parentAuthor;
+ final String? parentPermlink;
+ final List activeVotes;
+ final List blacklists;
+ final String? community;
+ final String? communityTitle;
+ final String? authorRole;
+ final String? authorTitle;
+ var visited = false;
+ final bool isLocallyAdded;
+
+ CommentItemModel(
+ {this.postId,
+ required this.author,
+ required this.permlink,
+ this.category,
+ this.title,
+ required this.body,
+ this.jsonMetadata,
+ required this.created,
+ this.updated,
+ required this.depth,
+ required this.children,
+ this.netRshares,
+ this.isPaidout,
+ this.payoutAt,
+ this.payout,
+ this.pendingPayoutValue,
+ this.authorPayoutValue,
+ this.curatorPayoutValue,
+ this.promoted,
+ this.replies = const [],
+ this.reblogs,
+ this.authorReputation,
+ this.stats,
+ this.url,
+ this.beneficiaries,
+ this.maxAcceptedPayout,
+ this.percentHbd,
+ this.parentAuthor,
+ this.parentPermlink,
+ this.activeVotes = const [],
+ this.blacklists = const [],
+ this.community,
+ this.communityTitle,
+ this.authorRole,
+ this.authorTitle,
+ this.isLocallyAdded = false});
+
+ CommentItemModel copyWith({
+ int? postId,
+ String? author,
+ String? permlink,
+ String? category,
+ String? title,
+ String? body,
+ CommentMetaDataModel? jsonMetadata,
+ DateTime? created,
+ DateTime? updated,
+ int? depth,
+ int? children,
+ int? netRshares,
+ bool? isPaidout,
+ DateTime? payoutAt,
+ double? payout,
+ String? pendingPayoutValue,
+ String? authorPayoutValue,
+ String? curatorPayoutValue,
+ String? promoted,
+ List? replies,
+ int? reblogs,
+ double? authorReputation,
+ Stats? stats,
+ String? url,
+ List? beneficiaries,
+ String? maxAcceptedPayout,
+ int? percentHbd,
+ String? parentAuthor,
+ String? parentPermlink,
+ List? activeVotes,
+ List? blacklists,
+ String? community,
+ String? communityTitle,
+ String? authorRole,
+ String? authorTitle,
+ }) {
+ return CommentItemModel(
+ postId: postId ?? this.postId,
+ author: author ?? this.author,
+ permlink: permlink ?? this.permlink,
+ category: category ?? this.category,
+ title: title ?? this.title,
+ body: body ?? this.body,
+ jsonMetadata: jsonMetadata ?? this.jsonMetadata,
+ created: created ?? this.created,
+ updated: updated ?? this.updated,
+ depth: depth ?? this.depth,
+ children: children ?? this.children,
+ netRshares: netRshares ?? this.netRshares,
+ isPaidout: isPaidout ?? this.isPaidout,
+ payoutAt: payoutAt ?? this.payoutAt,
+ payout: payout ?? this.payout,
+ pendingPayoutValue: pendingPayoutValue ?? this.pendingPayoutValue,
+ authorPayoutValue: authorPayoutValue ?? this.authorPayoutValue,
+ curatorPayoutValue: curatorPayoutValue ?? this.curatorPayoutValue,
+ promoted: promoted ?? this.promoted,
+ replies: replies ?? this.replies,
+ reblogs: reblogs ?? this.reblogs,
+ authorReputation: authorReputation ?? this.authorReputation,
+ stats: stats ?? this.stats,
+ url: url ?? this.url,
+ beneficiaries: beneficiaries ?? this.beneficiaries,
+ maxAcceptedPayout: maxAcceptedPayout ?? this.maxAcceptedPayout,
+ percentHbd: percentHbd ?? this.percentHbd,
+ parentAuthor: parentAuthor ?? this.parentAuthor,
+ parentPermlink: parentPermlink ?? this.parentPermlink,
+ activeVotes: activeVotes ?? this.activeVotes,
+ blacklists: blacklists ?? this.blacklists,
+ community: community ?? this.community,
+ communityTitle: communityTitle ?? this.communityTitle,
+ authorRole: authorRole ?? this.authorRole,
+ authorTitle: authorTitle ?? this.authorTitle,
+ );
+ }
+
+ factory CommentItemModel.fromRawJson(String str) =>
+ CommentItemModel.fromJson(json.decode(str));
+
+ String toRawJson() => json.encode(toJson());
+
+ factory CommentItemModel.fromJson(Map json) =>
+ CommentItemModel(
+ postId: json["post_id"],
+ author: json["author"],
+ permlink: json["permlink"],
+ category: json["category"],
+ title: json["title"],
+ body: json["body"],
+ jsonMetadata: json["json_metadata"] == null
+ ? null
+ : CommentMetaDataModel.fromJson(json["json_metadata"]),
+ created: DateTime.parse(json["created"]),
+ updated:
+ json["updated"] == null ? null : DateTime.parse(json["updated"]),
+ depth: json["depth"],
+ children: json["children"],
+ netRshares: json["net_rshares"],
+ isPaidout: json["is_paidout"],
+ payoutAt: json["payout_at"] == null
+ ? null
+ : DateTime.parse(json["payout_at"]),
+ payout: json["payout"]?.toDouble(),
+ pendingPayoutValue: json["pending_payout_value"],
+ authorPayoutValue: json["author_payout_value"],
+ curatorPayoutValue: json["curator_payout_value"],
+ promoted: json["promoted"],
+ replies: json["replies"] == null
+ ? []
+ : List.from(json["replies"]!.map((x) => x)),
+ reblogs: json["reblogs"],
+ authorReputation: json["author_reputation"]?.toDouble(),
+ stats: json["stats"] == null ? null : Stats.fromJson(json["stats"]),
+ url: json["url"],
+ beneficiaries: json["beneficiaries"] == null
+ ? []
+ : List.from(json["beneficiaries"]!.map((x) => x)),
+ maxAcceptedPayout: json["max_accepted_payout"],
+ percentHbd: json["percent_hbd"],
+ parentAuthor: json["parent_author"],
+ parentPermlink: json["parent_permlink"],
+ activeVotes: json["active_votes"] == null
+ ? []
+ : List.from(json["active_votes"]!
+ .map((x) => CommentActiveVote.fromJson(x))),
+ blacklists: json["blacklists"] == null
+ ? []
+ : List.from(json["blacklists"]!.map((x) => x)),
+ community: json["community"],
+ communityTitle: json["community_title"],
+ authorRole: json["author_role"],
+ authorTitle: json["author_title"],
+ );
+
+ Map toJson() => {
+ "post_id": postId,
+ "author": author,
+ "permlink": permlink,
+ "category": category,
+ "title": title,
+ "body": body,
+ "json_metadata": jsonMetadata?.toJson(),
+ "created": created.toIso8601String(),
+ "updated": updated?.toIso8601String(),
+ "depth": depth,
+ "children": children,
+ "net_rshares": netRshares,
+ "is_paidout": isPaidout,
+ "payout_at": payoutAt?.toIso8601String(),
+ "payout": payout,
+ "pending_payout_value": pendingPayoutValue,
+ "author_payout_value": authorPayoutValue,
+ "curator_payout_value": curatorPayoutValue,
+ "promoted": promoted,
+ "replies": List.from(replies.map((x) => x)),
+ "reblogs": reblogs,
+ "author_reputation": authorReputation,
+ "stats": stats?.toJson(),
+ "url": url,
+ "beneficiaries": beneficiaries == null
+ ? []
+ : List.from(beneficiaries!.map((x) => x)),
+ "max_accepted_payout": maxAcceptedPayout,
+ "percent_hbd": percentHbd,
+ "parent_author": parentAuthor,
+ "parent_permlink": parentPermlink,
+ "active_votes": List.from(activeVotes!.map((x) => x.toJson())),
+ "blacklists": List.from(blacklists!.map((x) => x)),
+ "community": community,
+ "community_title": communityTitle,
+ "author_role": authorRole,
+ "author_title": authorTitle,
+ };
+
+ @override
+ List get props =>
+ [postId, permlink, author, parentPermlink, parentAuthor, created];
+}
+
+class CommentActiveVote extends Equatable {
+ final int? rshares;
+ final String? voter;
+
+ CommentActiveVote({
+ this.rshares,
+ this.voter,
+ });
+
+ factory CommentActiveVote.fromRawJson(String str) =>
+ CommentActiveVote.fromJson(json.decode(str));
+
+ String toRawJson() => json.encode(toJson());
+
+ factory CommentActiveVote.fromJson(Map json) =>
+ CommentActiveVote(
+ rshares: json["rshares"],
+ voter: json["voter"],
+ );
+
+ Map toJson() => {
+ "rshares": rshares,
+ "voter": voter,
+ };
+
+ @override
+ List get props => [voter];
+}
+
+class CommentMetaDataModel {
+ final List? tags;
+ final String? app;
+
+ CommentMetaDataModel({
+ this.tags,
+ this.app,
+ });
+
+ factory CommentMetaDataModel.fromRawJson(String str) =>
+ CommentMetaDataModel.fromJson(json.decode(str));
+
+ String toRawJson() => json.encode(toJson());
+
+ factory CommentMetaDataModel.fromJson(Map json) =>
+ CommentMetaDataModel(
+ tags: json["tags"] == null
+ ? []
+ : json['tags'] is String ? [json['tags']] : List.from(json["tags"]!.map((x) => x)),
+ app: json["app"],
+ );
+
+ Map toJson() => {
+ "tags": tags == null ? [] : List.from(tags!.map((x) => x)),
+ "app": app,
+ };
+}
+
+class Stats {
+ final bool? hide;
+ final bool? gray;
+ final int? totalVotes;
+ final double? flagWeight;
+
+ Stats({
+ this.hide,
+ this.gray,
+ this.totalVotes,
+ this.flagWeight,
+ });
+
+ Stats copyWith({
+ bool? hide,
+ bool? gray,
+ int? totalVotes,
+ double? flagWeight,
+ }) {
+ return Stats(
+ hide: hide ?? this.hide,
+ gray: gray ?? this.gray,
+ totalVotes: totalVotes ?? this.totalVotes,
+ flagWeight: flagWeight ?? this.flagWeight,
+ );
+ }
+
+ factory Stats.fromRawJson(String str) => Stats.fromJson(json.decode(str));
+
+ String toRawJson() => json.encode(toJson());
+
+ factory Stats.fromJson(Map json) => Stats(
+ hide: json["hide"],
+ gray: json["gray"],
+ totalVotes: json["total_votes"],
+ flagWeight: json["flag_weight"],
+ );
+
+ Map toJson() => {
+ "hide": hide,
+ "gray": gray,
+ "total_votes": totalVotes,
+ "flag_weight": flagWeight,
+ };
+}
diff --git a/lib/src/models/hive_comments/request/hive_comment_request.dart b/lib/src/models/hive_comments/request/hive_comment_request.dart
new file mode 100644
index 00000000..5c4fe0d0
--- /dev/null
+++ b/lib/src/models/hive_comments/request/hive_comment_request.dart
@@ -0,0 +1,49 @@
+import 'package:acela/src/utils/safe_convert.dart';
+import 'dart:convert';
+
+String hiveCommentRequestToJson(HiveCommentRequest data) =>
+ json.encode(data.toJson());
+
+class HiveCommentRequest {
+ final List params;
+
+ // 2.0
+ final String jsonrpc;
+
+ // condenser_api.get_content_replies
+ final String method;
+
+ // 1
+ final int id;
+
+ HiveCommentRequest({
+ required this.params,
+ this.jsonrpc = "",
+ this.method = "",
+ this.id = 0,
+ });
+
+ factory HiveCommentRequest.from(List params) {
+ return HiveCommentRequest(
+ params: params,
+ method: "condenser_api.get_content_replies",
+ jsonrpc: "2.0",
+ id: 1,
+ );
+ }
+
+ factory HiveCommentRequest.fromJson(Map? json) =>
+ HiveCommentRequest(
+ params: asList(json, 'params').map((e) => e.toString()).toList(),
+ jsonrpc: asString(json, 'jsonrpc'),
+ method: asString(json, 'method'),
+ id: asInt(json, 'id'),
+ );
+
+ Map toJson() => {
+ 'params': params.map((e) => e).toList(),
+ 'jsonrpc': jsonrpc,
+ 'method': method,
+ 'id': id,
+ };
+}
diff --git a/lib/src/models/hive_comments/request/hive_comments_request.dart b/lib/src/models/hive_comments/request/hive_comments_request.dart
deleted file mode 100644
index 2244bcf4..00000000
--- a/lib/src/models/hive_comments/request/hive_comments_request.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-import 'dart:convert';
-
-String hiveCommentsRequestToJson(HiveCommentsRequest data) => json.encode(data.toJson());
-
-class HiveCommentsRequest {
- HiveCommentsRequest({required this.params});
- List params;
- var jsonrpc = "2.0";
- var method = "condenser_api.get_content_replies";
- var id = 1;
-
- factory HiveCommentsRequest.from(String author, String permlink) {
- return HiveCommentsRequest(params: [author, permlink]);
- }
-
- Map toJson() => {
- "jsonrpc": jsonrpc,
- "method": method,
- "id": id,
- "params": List.from(params.map((x) => x)),
- };
-}
-
-// {"jsonrpc":"2.0", "method":"condenser_api.get_content_replies", "params":["hiveio", "firstpost"], "id":1}
\ No newline at end of file
diff --git a/lib/src/models/hive_comments/response/active_vote.dart b/lib/src/models/hive_comments/response/active_vote.dart
new file mode 100644
index 00000000..7b5122ae
--- /dev/null
+++ b/lib/src/models/hive_comments/response/active_vote.dart
@@ -0,0 +1,44 @@
+import 'package:acela/src/utils/safe_convert.dart';
+
+class ActiveVote {
+ // 1000
+ final int percent;
+ // 784865040553638
+ final int reputation;
+ // 179995483613
+ final int rshares;
+ // 2022-02-06T04:25:57
+ final String time;
+ // jongolson
+ final String voter;
+ // 179995483613
+ final int weight;
+
+ ActiveVote({
+ this.percent = 0,
+ this.reputation = 0,
+ this.rshares = 0,
+ this.time = "",
+ this.voter = "",
+ this.weight = 0,
+ });
+
+ factory ActiveVote.fromJson(Map? json) => ActiveVote(
+ percent: asInt(json, 'percent'),
+ reputation: asInt(json, 'reputation'),
+ rshares: asInt(json, 'rshares'),
+ time: asString(json, 'time'),
+ voter: asString(json, 'voter'),
+ weight: asInt(json, 'weight'),
+ );
+
+ Map toJson() => {
+ 'percent': percent,
+ 'reputation': reputation,
+ 'rshares': rshares,
+ 'time': time,
+ 'voter': voter,
+ 'weight': weight,
+ };
+}
+
diff --git a/lib/src/models/hive_comments/response/hive_comments.dart b/lib/src/models/hive_comments/response/hive_comments.dart
index aacadbb0..9259af62 100644
--- a/lib/src/models/hive_comments/response/hive_comments.dart
+++ b/lib/src/models/hive_comments/response/hive_comments.dart
@@ -1,92 +1,117 @@
-// To parse this JSON data, do
-//
-// final hiveComments = hiveCommentsFromJson(jsonString);
-
import 'dart:convert';
-HiveComments hiveCommentsFromJson(String str) =>
- HiveComments.fromJson(json.decode(str));
+import 'package:acela/src/utils/safe_convert.dart';
+
+import 'active_vote.dart';
-String hiveCommentsToJson(HiveComments data) => json.encode(data.toJson());
+HiveComments hiveCommentsFromString(String string) {
+ return HiveComments.fromJson(json.decode(string));
+}
class HiveComments {
+ final String jsonrpc;
+ final List result;
+ final int id;
+
HiveComments({
+ this.jsonrpc = "",
required this.result,
+ this.id = 0,
});
- List result;
-
- factory HiveComments.fromJson(Map json) => HiveComments(
+ factory HiveComments.fromJson(Map? json) => HiveComments(
+ jsonrpc: asString(json, 'jsonrpc'),
result:
- List.from(json["result"].map((x) => HiveComment.fromJson(x))),
+ asList(json, 'result').map((e) => HiveComment.fromJson(e)).toList(),
+ id: asInt(json, 'id'),
);
Map toJson() => {
- "result": List.from(result.map((x) => x.toJson())),
+ 'jsonrpc': jsonrpc,
+ 'result': result.map((e) => e.toJson()),
+ 'id': id,
};
}
class HiveComment {
+ final String author;
+ final String permlink;
+ final String category;
+ final String body;
+ final String created;
+ final int depth;
+ final int children;
+ final String lastPayout;
+ final String cashoutTime;
+ final String totalPayoutValue;
+ final String curatorPayoutValue;
+ final String pendingPayoutValue;
+ final String parentAuthor;
+ final String parentPermlink;
+ final String url;
+ final List activeVotes;
+ final int? authorReputation;
+ final int? netRshares;
+
HiveComment({
- required this.author,
- required this.permlink,
- required this.body,
- required this.created,
- required this.depth,
- required this.children,
- required this.pendingPayoutValue,
- required this.parentPermlink,
+ this.author = "",
+ this.permlink = "",
+ this.category = "",
+ this.body = "",
+ this.created = "",
+ this.depth = 0,
+ this.children = 0,
+ this.lastPayout = "",
+ this.cashoutTime = "",
+ this.totalPayoutValue = "",
+ this.curatorPayoutValue = "",
+ this.pendingPayoutValue = "",
+ this.parentAuthor = "",
+ this.parentPermlink = "",
+ this.url = "",
required this.activeVotes,
+ required this.authorReputation,
+ required this.netRshares,
});
- String author;
- String permlink;
- String body;
- DateTime created;
- int depth;
- int children;
- String pendingPayoutValue;
- String parentPermlink;
- List activeVotes;
-
- factory HiveComment.fromJson(Map json) => HiveComment(
- author: json["author"],
- permlink: json["permlink"],
- body: json["body"],
- created: DateTime.parse(json["created"]),
- depth: json["depth"],
- children: json["children"],
- pendingPayoutValue: json["pending_payout_value"],
- parentPermlink: json["parent_permlink"],
- activeVotes: List.from(
- json["active_votes"].map((x) => ActiveVote.fromJson(x))),
- );
-
- Map toJson() => {
- "author": author,
- "permlink": permlink,
- "body": body,
- "created": created.toIso8601String(),
- "depth": depth,
- "children": children,
- "pending_payout_value": pendingPayoutValue,
- "parent_permlink": parentPermlink,
- "active_votes": List.from(activeVotes.map((x) => x.toJson())),
- };
-}
-
-class ActiveVote {
- ActiveVote({
- required this.percent,
- });
-
- int percent;
+ DateTime? get createdAt {
+ return DateTime.tryParse(created);
+ }
- factory ActiveVote.fromJson(Map json) => ActiveVote(
- percent: json["percent"],
+ factory HiveComment.fromJson(Map? json) => HiveComment(
+ author: asString(json, 'author'),
+ permlink: asString(json, 'permlink'),
+ category: asString(json, 'category'),
+ body: asString(json, 'body'),
+ created: asString(json, 'created'),
+ depth: asInt(json, 'depth'),
+ children: asInt(json, 'children'),
+ lastPayout: asString(json, 'last_payout'),
+ totalPayoutValue: asString(json, 'total_payout_value'),
+ pendingPayoutValue: asString(json, 'pending_payout_value'),
+ parentAuthor: asString(json, 'parent_author'),
+ parentPermlink: asString(json, 'parent_permlink'),
+ url: asString(json, 'url'),
+ authorReputation: asInt(json, 'author_reputation'),
+ netRshares: asInt(json, 'net_rshares'),
+ activeVotes: asList(json, 'active_votes')
+ .map((e) => ActiveVote.fromJson(json))
+ .toList(),
);
Map toJson() => {
- "percent": percent,
+ 'author': author,
+ 'permlink': permlink,
+ 'category': category,
+ 'body': body,
+ 'created': created,
+ 'depth': depth,
+ 'children': children,
+ 'last_payout': lastPayout,
+ 'total_payout_value': totalPayoutValue,
+ 'pending_payout_value': pendingPayoutValue,
+ 'parent_author': parentAuthor,
+ 'url': url,
+ 'active_votes': activeVotes.map((e) => e),
};
}
diff --git a/lib/src/models/hive_post_info/hive_post_info.dart b/lib/src/models/hive_post_info/hive_post_info.dart
new file mode 100644
index 00000000..456b1f59
--- /dev/null
+++ b/lib/src/models/hive_post_info/hive_post_info.dart
@@ -0,0 +1,103 @@
+import 'dart:convert';
+
+import 'package:acela/src/utils/safe_convert.dart';
+import 'package:equatable/equatable.dart';
+
+class HivePostInfo {
+ final String jsonrpc;
+ final HivePostInfoResult result;
+ final int id;
+
+ HivePostInfo({
+ this.jsonrpc = "",
+ required this.result,
+ this.id = 0,
+ });
+
+ factory HivePostInfo.fromJson(Map? json) => HivePostInfo(
+ jsonrpc: asString(json, 'jsonrpc'),
+ result: HivePostInfoResult.fromJson(asMap(json, 'result')),
+ id: asInt(json, 'id'),
+ );
+
+ factory HivePostInfo.fromJsonString(String jsonString) =>
+ HivePostInfo.fromJson(json.decode(jsonString));
+}
+
+class HivePostInfoResult {
+ final List resultData;
+
+ HivePostInfoResult({
+ required this.resultData,
+ });
+
+ factory HivePostInfoResult.fromJson(Map? json) {
+ var result = json?.keys.map((e) => HivePostInfoPostResultBody.fromJson(
+ json[e] as Map)) ??
+ [];
+ return HivePostInfoResult(resultData: result.toList());
+ }
+}
+
+class HivePostInfoPostResultBody {
+ final double payout;
+ final List activeVotes;
+ final String permlink;
+
+ HivePostInfoPostResultBody({
+ required this.payout,
+ required this.activeVotes,
+ required this.permlink,
+ });
+
+ HivePostInfoPostResultBody copyWith({
+ double? payout,
+ List? activeVotes,
+ String? permlink,
+ }) {
+ return HivePostInfoPostResultBody(
+ payout: payout ?? this.payout,
+ activeVotes: activeVotes ?? this.activeVotes,
+ permlink: permlink ?? this.permlink,
+ );
+ }
+
+ factory HivePostInfoPostResultBody.fromJson(Map? json) =>
+ HivePostInfoPostResultBody(
+ payout: asDouble(json, 'payout'),
+ permlink: asString(json, 'permlink'),
+ activeVotes: asList(json, 'active_votes')
+ .map((e) => ActiveVotesItem.fromJson(e))
+ .toList(),
+ );
+
+ Map toJson() => {
+ 'payout': payout,
+ 'permlink': permlink,
+ 'active_votes': activeVotes.map((e) => e.toJson()),
+ };
+}
+
+class ActiveVotesItem extends Equatable {
+ final int rshares;
+ final String voter;
+
+ const ActiveVotesItem({
+ this.rshares = 0,
+ this.voter = "",
+ });
+
+ factory ActiveVotesItem.fromJson(Map? json) =>
+ ActiveVotesItem(
+ rshares: asInt(json, 'rshares'),
+ voter: asString(json, 'voter'),
+ );
+
+ Map toJson() => {
+ 'rshares': rshares,
+ 'voter': voter,
+ };
+
+ @override
+ List get props => [voter];
+}
diff --git a/lib/src/models/hive_post_info/hive_user_posting_key.dart b/lib/src/models/hive_post_info/hive_user_posting_key.dart
new file mode 100644
index 00000000..c60c3b5a
--- /dev/null
+++ b/lib/src/models/hive_post_info/hive_user_posting_key.dart
@@ -0,0 +1,26 @@
+import 'dart:convert';
+
+import 'package:acela/src/utils/safe_convert.dart';
+
+class HiveUserPostingKey {
+ final String publicPostingKey;
+
+ HiveUserPostingKey({
+ required this.publicPostingKey,
+ });
+
+ factory HiveUserPostingKey.fromJson(Map? json) {
+ var resultMap = asMap(json, 'result');
+ var accounts = asList(resultMap, 'accounts');
+ if (accounts.isEmpty) throw 'accounts is empty';
+ var postingMap = asMap(accounts[0], 'posting');
+ var keyAuthsTopLevel = asList(postingMap, 'key_auths');
+ if (keyAuthsTopLevel.isEmpty) throw 'Posting Key auths top level empty';
+ var firstKeyAuth = keyAuthsTopLevel[0] as List;
+ var postingPublicKey = firstKeyAuth[0] as String;
+ return HiveUserPostingKey(publicPostingKey: postingPublicKey);
+ }
+
+ factory HiveUserPostingKey.fromString(String string) =>
+ HiveUserPostingKey.fromJson(json.decode(string));
+}
diff --git a/lib/src/models/home_screen_feed_models/hive_payout_response.dart b/lib/src/models/home_screen_feed_models/hive_payout_response.dart
new file mode 100644
index 00000000..cff10fba
--- /dev/null
+++ b/lib/src/models/home_screen_feed_models/hive_payout_response.dart
@@ -0,0 +1,49 @@
+import 'dart:convert';
+import 'package:acela/src/utils/safe_convert.dart';
+
+class HivePayoutResponse {
+ final String jsonrpc;
+ final HivePayoutResponseResult result;
+
+ HivePayoutResponse({
+ this.jsonrpc = "",
+ required this.result,
+ });
+
+ factory HivePayoutResponse.fromJson(Map? json) => HivePayoutResponse(
+ jsonrpc: asString(json, 'jsonrpc'),
+ result: HivePayoutResponseResult.fromJson(asMap(json, 'result')),
+ );
+
+ factory HivePayoutResponse.fromJsonString(String jsonString) => HivePayoutResponse.fromJson(json.decode(jsonString));
+
+ Map toJson() => {
+ 'jsonrpc': jsonrpc,
+ 'result': result.toJson(),
+ };
+}
+
+class HivePayoutResponseResult {
+ final String totalPayoutValue;
+ final String curatorPayoutValue;
+ final String pendingPayoutValue;
+
+ HivePayoutResponseResult({
+ this.totalPayoutValue = "",
+ this.curatorPayoutValue = "",
+ this.pendingPayoutValue = "",
+ });
+
+ factory HivePayoutResponseResult.fromJson(Map? json) => HivePayoutResponseResult(
+ totalPayoutValue: asString(json, 'total_payout_value'),
+ curatorPayoutValue: asString(json, 'curator_payout_value'),
+ pendingPayoutValue: asString(json, 'pending_payout_value'),
+ );
+
+ Map toJson() => {
+ 'total_payout_value': totalPayoutValue,
+ 'curator_payout_value': curatorPayoutValue,
+ 'pending_payout_value': pendingPayoutValue,
+ };
+}
+
diff --git a/lib/src/models/home_screen_feed_models/home_feed.dart b/lib/src/models/home_screen_feed_models/home_feed.dart
new file mode 100644
index 00000000..fb8da12f
--- /dev/null
+++ b/lib/src/models/home_screen_feed_models/home_feed.dart
@@ -0,0 +1,132 @@
+import 'dart:convert';
+
+import 'package:acela/src/models/user_stream/hive_user_stream.dart';
+import 'package:acela/src/utils/safe_convert.dart';
+
+// final jsonList = json.decode(jsonStr) as List;
+// final list = jsonList.map((e) => HomeFeedItem.fromJson(e)).toList();
+
+List homeFeedItemFromString(String string) {
+ final jsonList = json.decode(string) as List;
+ final list = jsonList.map((e) => HomeFeedItem.fromJson(e)).toList();
+ return list;
+}
+
+class PayoutInfo {
+ double? payout;
+ int? upVotes;
+ int? downVotes;
+ PayoutInfo({
+ required this.payout,
+ required this.upVotes,
+ required this.downVotes,
+ });
+}
+
+class HomeFeedItem {
+ final String created;
+ final String language;
+ final int views;
+ final String author;
+ final String permlink;
+ final String title;
+ final double duration;
+ final bool isNsfw;
+ final List tags;
+ final bool isIpfs;
+ final String playUrl;
+ final String ipfs;
+ final HomeFeedItemImage images;
+ final bool isShorts;
+
+ HomeFeedItem({
+ this.created = "",
+ this.language = "",
+ this.views = 0,
+ this.author = "",
+ this.permlink = "",
+ this.title = "",
+ this.duration = 0.0,
+ this.isNsfw = false,
+ required this.tags,
+ this.isIpfs = false,
+ this.playUrl = "",
+ this.ipfs = "",
+ required this.images,
+ required this.isShorts,
+ });
+
+ String getVideoUrl(HiveUserData data) {
+ // return playUrl;
+ if (playUrl.contains('ipfs')) {
+ // example
+ // https://ipfs-3speak.b-cdn.net/ipfs/QmTRDJcgtt66pxs3ZnQCdRw57b69NS2TQvF4yHwaux5grT/manifest.m3u8
+ // https://ipfs-3speak.b-cdn.net/ipfs/QmTRDJcgtt66pxs3ZnQCdRw57b69NS2TQvF4yHwaux5grT/480p/index.m3u8
+ return playUrl.replaceAll('manifest', '${data.resolution}/index');
+ } else {
+ // example
+ // https://threespeakvideo.b-cdn.net/chjwguvd/default.m3u8
+ // https://threespeakvideo.b-cdn.net/chjwguvd/480p.m3u8
+ return playUrl.replaceAll('default', '${data.resolution}');
+ }
+ }
+
+ DateTime? get createdAt {
+ return DateTime.tryParse(created);
+ }
+
+ factory HomeFeedItem.fromJson(Map? json) => HomeFeedItem(
+ created: asString(json, 'created'),
+ language: asString(json, 'language'),
+ views: asInt(json, 'views'),
+ author: asString(json, 'author'),
+ permlink: asString(json, 'permlink'),
+ title: asString(json, 'title'),
+ duration: asDouble(json, 'duration'),
+ isNsfw: asBool(json, 'isNsfw'),
+ tags: asList(json, 'tags').map((e) => e.toString()).toList(),
+ isIpfs: asBool(json, 'isIpfs'),
+ playUrl: asString(json, 'playUrl'),
+ ipfs: asString(json, 'ipfs'),
+ isShorts: asBool(json, 'isShorts'),
+ images: HomeFeedItemImage.fromJson(asMap(json, 'images')),
+ );
+
+ Map toJson() => {
+ 'created': created,
+ 'language': language,
+ 'views': views,
+ 'author': author,
+ 'permlink': permlink,
+ 'title': title,
+ 'duration': duration,
+ 'isNsfw': isNsfw,
+ 'tags': tags.map((e) => e),
+ 'isIpfs': isIpfs,
+ 'playUrl': playUrl,
+ 'ipfs': ipfs,
+ 'isShorts': isShorts,
+ 'images': images.toJson(),
+ };
+}
+
+class HomeFeedItemImage {
+ final String ipfsThumbnail;
+ final String thumbnail;
+
+ HomeFeedItemImage({
+ this.ipfsThumbnail = "",
+ this.thumbnail = "",
+ });
+
+ factory HomeFeedItemImage.fromJson(Map? json) =>
+ HomeFeedItemImage(
+ ipfsThumbnail: asString(json, 'ipfs_thumbnail'),
+ thumbnail: asString(json, 'thumbnail'),
+ );
+
+ Map toJson() => {
+ 'ipfs_thumbnail': ipfsThumbnail,
+ 'thumbnail': thumbnail,
+ };
+}
diff --git a/lib/src/models/home_screen_feed_models/home_feed_models.dart b/lib/src/models/home_screen_feed_models/home_feed_models.dart
deleted file mode 100644
index 21e02279..00000000
--- a/lib/src/models/home_screen_feed_models/home_feed_models.dart
+++ /dev/null
@@ -1,100 +0,0 @@
-import 'dart:convert';
-
-List homeFeedFromJson(String str) => List.from(json.decode(str).map((x) => HomeFeed.fromJson(x)));
-
-String homeFeedToJson(List data) => json.encode(List.from(data.map((x) => x.toJson())));
-
-class HomeFeed {
- HomeFeed({
- required this.created,
- required this.views,
- required this.owner,
- required this.permlink,
- required this.title,
- required this.duration,
- required this.isNsfwContent,
- required this.tags_v2,
- required this.thumbUrl,
- required this.baseThumbUrl,
- this.ipfs,
- });
-
- DateTime created;
- int views;
- String owner;
- String permlink;
- String title;
- double duration;
- bool isNsfwContent;
- List tags_v2;
- String? ipfs;
- String thumbUrl;
- String baseThumbUrl;
-
- factory HomeFeed.fromJson(Map json) {
- final created = json['created'] as String?;
- if (created == null) {
- throw UnsupportedError('Invalid data: $json -> "created" is missing');
- }
- final int? views = json['views'] as int?;
- if (views == null) {
- throw UnsupportedError('Invalid data: $json -> "views" is missing');
- }
- final owner = json['owner'] as String?;
- if (owner == null) {
- throw UnsupportedError('Invalid data: $json -> "owner" is missing');
- }
- final permlink = json['permlink'] as String?;
- if (permlink == null) {
- throw UnsupportedError('Invalid data: $json -> "permlink" is missing');
- }
- final title = json['title'] as String?;
- if (title == null) {
- throw UnsupportedError('Invalid data: $json -> "title" is missing');
- }
- final double? duration = double.parse(json['duration'].toString());
- if (duration == null) {
- throw UnsupportedError('Invalid data: $json -> "duration" is missing');
- }
- final bool? isNsfwContent = json['isNsfwContent'] as bool?;
- if (isNsfwContent == null) {
- throw UnsupportedError('Invalid data: $json -> "isNsfwContent" is missing');
- }
- final thumbUrl = json['thumbUrl'] as String?;
- if (thumbUrl == null) {
- throw UnsupportedError('Invalid data: $json -> "thumbUrl" is missing');
- }
- final baseThumbUrl = json['baseThumbUrl'] as String?;
- if (baseThumbUrl == null) {
- throw UnsupportedError('Invalid data: $json -> "baseThumbUrl" is missing');
- }
- final ipfs = json['ipfs'] as String?;
- return HomeFeed(
- created: DateTime.parse(created),
- views: views,
- owner: owner,
- permlink: permlink,
- title: title,
- duration: duration,
- isNsfwContent: isNsfwContent,
- tags_v2: json["tags_v2"] == null ? [] : List.from(json["tags_v2"].map((x) => x)),
- ipfs: ipfs,
- thumbUrl: thumbUrl,
- baseThumbUrl: baseThumbUrl,
- );
- }
-
- Map toJson() => {
- "created": created.toIso8601String(),
- "views": views,
- "owner": owner,
- "permlink": permlink,
- "title": title,
- "duration": duration,
- "isNsfwContent": isNsfwContent,
- "tags_v2": List.from(tags_v2.map((x) => x)),
- "thumbUrl": thumbUrl,
- "baseThumbUrl": baseThumbUrl,
- "ipfs": ipfs,
- };
-}
\ No newline at end of file
diff --git a/lib/src/models/leaderboard_models/leaderboard_model.dart b/lib/src/models/leaderboard_models/leaderboard_model.dart
new file mode 100644
index 00000000..52b80b92
--- /dev/null
+++ b/lib/src/models/leaderboard_models/leaderboard_model.dart
@@ -0,0 +1,39 @@
+import 'dart:convert';
+import 'package:acela/src/utils/safe_convert.dart';
+
+List leaderboardResponseItemFromString(String string) {
+ final jsonList = json.decode(string) as List;
+ final list =
+ jsonList.map((e) => LeaderboardResponseItem.fromJson(e)).toList();
+ return list;
+}
+
+class LeaderboardResponseItem {
+ // 735
+ final int rank;
+
+ // 667.6
+ final double score;
+
+ // mrosenquist1
+ final String username;
+
+ LeaderboardResponseItem({
+ this.rank = 0,
+ this.score = 0.0,
+ this.username = "",
+ });
+
+ factory LeaderboardResponseItem.fromJson(Map? json) =>
+ LeaderboardResponseItem(
+ rank: asInt(json, 'rank'),
+ score: asDouble(json, 'score'),
+ username: asString(json, 'username'),
+ );
+
+ Map toJson() => {
+ 'rank': rank,
+ 'score': score,
+ 'username': username,
+ };
+}
diff --git a/lib/src/models/login/login_bridge_response.dart b/lib/src/models/login/login_bridge_response.dart
new file mode 100644
index 00000000..2c96b27c
--- /dev/null
+++ b/lib/src/models/login/login_bridge_response.dart
@@ -0,0 +1,35 @@
+import 'dart:convert';
+
+import 'package:acela/src/utils/safe_convert.dart';
+
+class LoginBridgeResponse {
+ final bool valid;
+ final String? accountName;
+ final String error;
+ final String? data;
+
+ LoginBridgeResponse({
+ required this.valid,
+ required this.accountName,
+ required this.error,
+ required this.data,
+ });
+
+ factory LoginBridgeResponse.fromJson(Map? json) =>
+ LoginBridgeResponse(
+ valid: asBool(json, 'valid'),
+ accountName: asString(json, 'accountName'),
+ error: asString(json, 'error'),
+ data: asString(json, 'data'),
+ );
+
+ factory LoginBridgeResponse.fromJsonString(String jsonString) =>
+ LoginBridgeResponse.fromJson(json.decode(jsonString));
+
+ Map toJson() => {
+ 'valid': valid,
+ 'accountName': accountName,
+ 'error': error,
+ 'data': data,
+ };
+}
diff --git a/lib/src/models/login/memo_response.dart b/lib/src/models/login/memo_response.dart
new file mode 100644
index 00000000..31201a05
--- /dev/null
+++ b/lib/src/models/login/memo_response.dart
@@ -0,0 +1,30 @@
+import 'dart:convert';
+
+import 'package:acela/src/utils/safe_convert.dart';
+
+class MemoResponse {
+ final String error;
+ final String accountName;
+ final String decrypted;
+
+ MemoResponse({
+ this.error = "",
+ this.accountName = "",
+ this.decrypted = "",
+ });
+
+ factory MemoResponse.fromJson(Map? json) => MemoResponse(
+ error: asString(json, 'error'),
+ accountName: asString(json, 'accountName'),
+ decrypted: asString(json, 'decrypted'),
+ );
+
+ factory MemoResponse.fromJsonString(String jsonString) =>
+ MemoResponse.fromJson(json.decode(jsonString));
+
+ Map toJson() => {
+ 'error': error,
+ 'accountName': accountName,
+ 'decrypted': decrypted,
+ };
+}
diff --git a/lib/src/models/my_account/my_devices.dart b/lib/src/models/my_account/my_devices.dart
new file mode 100644
index 00000000..e94904b5
--- /dev/null
+++ b/lib/src/models/my_account/my_devices.dart
@@ -0,0 +1,49 @@
+import 'dart:convert';
+
+import 'package:acela/src/utils/safe_convert.dart';
+
+class MyDevices {
+ final bool success;
+ final List data;
+
+ MyDevices({
+ this.success = false,
+ required this.data,
+ });
+
+ factory MyDevices.fromJson(Map? json) => MyDevices(
+ success: asBool(json, 'success'),
+ data: asList(json, 'data')
+ .map((e) => MyDevicesDataItem.fromJson(e))
+ .toList(),
+ );
+
+ factory MyDevices.fromString(String string) =>
+ MyDevices.fromJson(json.decode(string));
+
+ Map toJson() => {
+ 'success': success,
+ 'data': data.map((e) => e.toJson()),
+ };
+}
+
+class MyDevicesDataItem {
+ final String token;
+ final String deviceName;
+
+ MyDevicesDataItem({
+ this.token = "",
+ this.deviceName = "",
+ });
+
+ factory MyDevicesDataItem.fromJson(Map? json) =>
+ MyDevicesDataItem(
+ token: asString(json, 'token'),
+ deviceName: asString(json, 'deviceName'),
+ );
+
+ Map toJson() => {
+ 'token': token,
+ 'deviceName': deviceName,
+ };
+}
diff --git a/lib/src/models/my_account/video_ops.dart b/lib/src/models/my_account/video_ops.dart
new file mode 100644
index 00000000..b893343a
--- /dev/null
+++ b/lib/src/models/my_account/video_ops.dart
@@ -0,0 +1,88 @@
+import 'dart:convert';
+
+import 'package:acela/src/utils/safe_convert.dart';
+import 'package:equatable/equatable.dart';
+
+class VideoOpsResponse {
+ final bool success;
+ VideoOpsResponse({
+ required this.success,
+ });
+
+ factory VideoOpsResponse.fromJson(Map? json) =>
+ VideoOpsResponse(
+ success: asBool(json, 'success'),
+ );
+
+ factory VideoOpsResponse.fromJsonString(String jsonString) =>
+ VideoOpsResponse.fromJson(json.decode(jsonString));
+}
+
+class ErrorResponse {
+ final String? error;
+ ErrorResponse({
+ required this.error,
+ });
+
+ factory ErrorResponse.fromJson(Map? json) => ErrorResponse(
+ error: asString(json, 'error'),
+ );
+
+ factory ErrorResponse.fromJsonString(String jsonString) =>
+ ErrorResponse.fromJson(json.decode(jsonString));
+}
+
+class BeneficiariesJson extends Equatable {
+ final String account;
+ int weight;
+ final String src;
+ final bool isDefault;
+
+ BeneficiariesJson(
+ {required this.account,
+ required this.weight,
+ required this.src,
+ this.isDefault = false});
+
+ factory BeneficiariesJson.fromJson(Map? json) =>
+ BeneficiariesJson(
+ account: asString(json, 'account'),
+ weight: asInt(json, 'weight'),
+ src: asString(json, 'src'),
+ );
+
+ static List fromJsonString(String jsonString) {
+ var list = json.decode(jsonString) as List;
+ var listNew = list.map((e) => BeneficiariesJson.fromJson(e)).toList();
+ return listNew;
+ }
+
+ static String toJsonString(List