Compare commits
No commits in common. "master" and "1.6.1+19" have entirely different histories.
36 changed files with 410 additions and 880 deletions
21
.drone.yml
Normal file
21
.drone.yml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: build
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
event:
|
||||||
|
include:
|
||||||
|
- push
|
||||||
|
- pull_request
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: build
|
||||||
|
image: ghcr.io/cirruslabs/flutter:3.10.2
|
||||||
|
commands:
|
||||||
|
- flutter doctor
|
||||||
|
- flutter pub get
|
||||||
|
- flutter pub outdated
|
||||||
|
- flutter packages pub run build_runner build --delete-conflicting-outputs
|
||||||
|
- flutter analyze --no-pub --no-current-package lib/
|
||||||
|
- flutter build apk --debug
|
|
@ -1,21 +0,0 @@
|
||||||
on: [ push ]
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: docker
|
|
||||||
container:
|
|
||||||
image: ghcr.io/cirruslabs/flutter:3.24.4
|
|
||||||
steps:
|
|
||||||
- name: Prepare requirements
|
|
||||||
run: |
|
|
||||||
apt-get update
|
|
||||||
apt-get install -y nodejs npm git
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Build
|
|
||||||
run: |
|
|
||||||
flutter doctor
|
|
||||||
flutter pub get
|
|
||||||
flutter pub outdated
|
|
||||||
flutter packages pub run build_runner build --delete-conflicting-outputs
|
|
||||||
flutter analyze --no-pub --no-current-package lib/
|
|
||||||
flutter build apk --debug
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,7 +1,6 @@
|
||||||
# Miscellaneous
|
# Miscellaneous
|
||||||
*.class
|
*.class
|
||||||
*.lock
|
*.lock
|
||||||
!Gemfile.lock
|
|
||||||
!pubspec.lock
|
!pubspec.lock
|
||||||
*.log
|
*.log
|
||||||
*.pyc
|
*.pyc
|
||||||
|
|
15
CHANGELOG.md
15
CHANGELOG.md
|
@ -1,20 +1,5 @@
|
||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
## 1.6.4+22 - 2024/11/01
|
|
||||||
* Dependency updates
|
|
||||||
* Internal build updates
|
|
||||||
|
|
||||||
## 1.6.3+21
|
|
||||||
* Fixed not receiving share requests from other applications
|
|
||||||
|
|
||||||
## 1.6.2+20
|
|
||||||
* Updated internal dependencies
|
|
||||||
* Moved progress indicator of _Show Configuration_ into the underlying button
|
|
||||||
* Bumped Android minSdk to `30` (Android 11)
|
|
||||||
* Bumped Android targetSdk to `34` (Android 14)
|
|
||||||
* Fixed permission service not handling Android SDK 33 correctly
|
|
||||||
* Fixed permission service not being started during application start
|
|
||||||
|
|
||||||
## 1.6.1+19
|
## 1.6.1+19
|
||||||
* Updated internal dependencies
|
* Updated internal dependencies
|
||||||
|
|
||||||
|
|
31
README.md
31
README.md
|
@ -2,8 +2,7 @@
|
||||||
|
|
||||||
A mobile flutter app for [FileBin](https://git.server-speed.net/users/flo/filebin/).
|
A mobile flutter app for [FileBin](https://git.server-speed.net/users/flo/filebin/).
|
||||||
|
|
||||||
Available on the [Play Store](https://play.google.com/store/apps/details?id=de.varakh.fbmobile) and
|
Available on the [Play Store](https://play.google.com/store/apps/details?id=de.varakh.fbmobile).
|
||||||
[IzzyOnDroid](https://apt.izzysoft.de/fdroid/index/apk/de.varakh.fbmobile/).
|
|
||||||
|
|
||||||
The main git repository is hosted at **[https://git.myservermanager.com/varakh/fbmobile](https://git.myservermanager.com/varakh/fbmobile)**.
|
The main git repository is hosted at **[https://git.myservermanager.com/varakh/fbmobile](https://git.myservermanager.com/varakh/fbmobile)**.
|
||||||
Other repositories are mirrors and pull requests, issues, and planning are managed there.
|
Other repositories are mirrors and pull requests, issues, and planning are managed there.
|
||||||
|
@ -95,7 +94,7 @@ profiles. They're stored in a separate git repository and are encrypted.
|
||||||
|
|
||||||
You need access to the git repository in which those private files reside.
|
You need access to the git repository in which those private files reside.
|
||||||
|
|
||||||
#### Usage / doing the actual release
|
#### Usage
|
||||||
|
|
||||||
Go into the platform directory you want to build for, e.g. `ios/` or `android/` and then look into the
|
Go into the platform directory you want to build for, e.g. `ios/` or `android/` and then look into the
|
||||||
`Fastlane` file which lanes are present. Run a lane via `fastlane <platform> <lane>`, e.g. use the
|
`Fastlane` file which lanes are present. Run a lane via `fastlane <platform> <lane>`, e.g. use the
|
||||||
|
@ -105,37 +104,13 @@ following to build for Android `fastlane android build`.
|
||||||
|
|
||||||
##### Android
|
##### Android
|
||||||
|
|
||||||
It's recommended you set up `fastlane` via `bundler` (you need this to be installed on your machine).
|
Use `fastlane android beta` to build and upload a new beta version to the Play Store.
|
||||||
|
|
||||||
Go into the `android/` sub-directory of the project
|
|
||||||
|
|
||||||
```shell
|
|
||||||
bundle config set --local path 'vendor/bundle'
|
|
||||||
bundle install
|
|
||||||
|
|
||||||
# update fastlane when needed
|
|
||||||
bundle update fastlane
|
|
||||||
|
|
||||||
# build only
|
|
||||||
bundle exec fastlane android build
|
|
||||||
|
|
||||||
# deploy (push BETA to app store)
|
|
||||||
bundle exec fastlane android beta
|
|
||||||
|
|
||||||
# deploy (push to app store)
|
|
||||||
bundle exec fastlane android deploy
|
|
||||||
|
|
||||||
# deploy (build signed fdroid large bundle [no target and abi split])
|
|
||||||
bundle exec fastlane android build_production_fdroid
|
|
||||||
```
|
|
||||||
|
|
||||||
##### iOS
|
##### iOS
|
||||||
|
|
||||||
For iOS you need to execute `fastlane ios build` before uploading to testflight with
|
For iOS you need to execute `fastlane ios build` before uploading to testflight with
|
||||||
`fastlane ios beta`.
|
`fastlane ios beta`.
|
||||||
|
|
||||||
Probably do the same Ruby/fastlane setup as mentioned under the _Android_ section.
|
|
||||||
|
|
||||||
### Release manually (not recommended)
|
### Release manually (not recommended)
|
||||||
|
|
||||||
See the following links on how to setup:
|
See the following links on how to setup:
|
||||||
|
|
2
android/.gitignore
vendored
2
android/.gitignore
vendored
|
@ -5,5 +5,3 @@ gradle-wrapper.jar
|
||||||
/gradlew.bat
|
/gradlew.bat
|
||||||
/local.properties
|
/local.properties
|
||||||
GeneratedPluginRegistrant.java
|
GeneratedPluginRegistrant.java
|
||||||
.bundle
|
|
||||||
vendor/
|
|
||||||
|
|
|
@ -1,222 +0,0 @@
|
||||||
GEM
|
|
||||||
remote: https://rubygems.org/
|
|
||||||
specs:
|
|
||||||
CFPropertyList (3.0.7)
|
|
||||||
base64
|
|
||||||
nkf
|
|
||||||
rexml
|
|
||||||
addressable (2.8.7)
|
|
||||||
public_suffix (>= 2.0.2, < 7.0)
|
|
||||||
artifactory (3.0.17)
|
|
||||||
atomos (0.1.3)
|
|
||||||
aws-eventstream (1.3.0)
|
|
||||||
aws-partitions (1.1000.0)
|
|
||||||
aws-sdk-core (3.211.0)
|
|
||||||
aws-eventstream (~> 1, >= 1.3.0)
|
|
||||||
aws-partitions (~> 1, >= 1.992.0)
|
|
||||||
aws-sigv4 (~> 1.9)
|
|
||||||
jmespath (~> 1, >= 1.6.1)
|
|
||||||
aws-sdk-kms (1.95.0)
|
|
||||||
aws-sdk-core (~> 3, >= 3.210.0)
|
|
||||||
aws-sigv4 (~> 1.5)
|
|
||||||
aws-sdk-s3 (1.169.0)
|
|
||||||
aws-sdk-core (~> 3, >= 3.210.0)
|
|
||||||
aws-sdk-kms (~> 1)
|
|
||||||
aws-sigv4 (~> 1.5)
|
|
||||||
aws-sigv4 (1.10.1)
|
|
||||||
aws-eventstream (~> 1, >= 1.0.2)
|
|
||||||
babosa (1.0.4)
|
|
||||||
base64 (0.2.0)
|
|
||||||
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.6.20240107)
|
|
||||||
dotenv (2.8.1)
|
|
||||||
emoji_regex (3.2.3)
|
|
||||||
excon (0.112.0)
|
|
||||||
faraday (1.10.4)
|
|
||||||
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.2)
|
|
||||||
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.1)
|
|
||||||
faraday (~> 1.0)
|
|
||||||
fastimage (2.3.1)
|
|
||||||
fastlane (2.225.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 (~> 1.2)
|
|
||||||
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)
|
|
||||||
fastlane-sirp (>= 1.0.0)
|
|
||||||
gh_inspector (>= 1.1.2, < 2.0.0)
|
|
||||||
google-apis-androidpublisher_v3 (~> 0.3)
|
|
||||||
google-apis-playcustomapp_v1 (~> 0.1)
|
|
||||||
google-cloud-env (>= 1.6.0, < 2.0.0)
|
|
||||||
google-cloud-storage (~> 1.31)
|
|
||||||
highline (~> 2.0)
|
|
||||||
http-cookie (~> 1.0.5)
|
|
||||||
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, < 1.0.0)
|
|
||||||
plist (>= 3.1.0, < 4.0.0)
|
|
||||||
rubyzip (>= 2.0.0, < 3.0.0)
|
|
||||||
security (= 0.1.5)
|
|
||||||
simctl (~> 1.6.3)
|
|
||||||
terminal-notifier (>= 2.0.0, < 3.0.0)
|
|
||||||
terminal-table (~> 3)
|
|
||||||
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, < 2.0.0)
|
|
||||||
fastlane-sirp (1.0.0)
|
|
||||||
sysrandom (~> 1.0)
|
|
||||||
gh_inspector (1.1.3)
|
|
||||||
google-apis-androidpublisher_v3 (0.54.0)
|
|
||||||
google-apis-core (>= 0.11.0, < 2.a)
|
|
||||||
google-apis-core (0.11.3)
|
|
||||||
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
|
|
||||||
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.31.0)
|
|
||||||
google-apis-core (>= 0.11.0, < 2.a)
|
|
||||||
google-cloud-core (1.7.1)
|
|
||||||
google-cloud-env (>= 1.0, < 3.a)
|
|
||||||
google-cloud-errors (~> 1.0)
|
|
||||||
google-cloud-env (1.6.0)
|
|
||||||
faraday (>= 0.17.3, < 3.0)
|
|
||||||
google-cloud-errors (1.4.0)
|
|
||||||
google-cloud-storage (1.47.0)
|
|
||||||
addressable (~> 2.8)
|
|
||||||
digest-crc (~> 0.4)
|
|
||||||
google-apis-iamcredentials_v1 (~> 0.1)
|
|
||||||
google-apis-storage_v1 (~> 0.31.0)
|
|
||||||
google-cloud-core (~> 1.6)
|
|
||||||
googleauth (>= 0.16.2, < 2.a)
|
|
||||||
mini_mime (~> 1.0)
|
|
||||||
googleauth (1.8.1)
|
|
||||||
faraday (>= 0.17.3, < 3.a)
|
|
||||||
jwt (>= 1.4, < 3.0)
|
|
||||||
multi_json (~> 1.11)
|
|
||||||
os (>= 0.9, < 2.0)
|
|
||||||
signet (>= 0.16, < 2.a)
|
|
||||||
highline (2.0.3)
|
|
||||||
http-cookie (1.0.7)
|
|
||||||
domain_name (~> 0.5)
|
|
||||||
httpclient (2.8.3)
|
|
||||||
jmespath (1.6.2)
|
|
||||||
json (2.7.5)
|
|
||||||
jwt (2.9.3)
|
|
||||||
base64
|
|
||||||
mini_magick (4.13.2)
|
|
||||||
mini_mime (1.1.5)
|
|
||||||
multi_json (1.15.0)
|
|
||||||
multipart-post (2.4.1)
|
|
||||||
nanaimo (0.4.0)
|
|
||||||
naturally (2.2.1)
|
|
||||||
nkf (0.2.0)
|
|
||||||
optparse (0.5.0)
|
|
||||||
os (1.1.4)
|
|
||||||
plist (3.7.1)
|
|
||||||
public_suffix (6.0.1)
|
|
||||||
rake (13.2.1)
|
|
||||||
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.3.9)
|
|
||||||
rouge (2.0.7)
|
|
||||||
ruby2_keywords (0.0.5)
|
|
||||||
rubyzip (2.3.2)
|
|
||||||
security (0.1.5)
|
|
||||||
signet (0.19.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
|
|
||||||
sysrandom (1.0.5)
|
|
||||||
terminal-notifier (2.0.0)
|
|
||||||
terminal-table (3.0.2)
|
|
||||||
unicode-display_width (>= 1.1.1, < 3)
|
|
||||||
trailblazer-option (0.1.2)
|
|
||||||
tty-cursor (0.7.1)
|
|
||||||
tty-screen (0.8.2)
|
|
||||||
tty-spinner (0.9.3)
|
|
||||||
tty-cursor (~> 0.7)
|
|
||||||
uber (0.1.0)
|
|
||||||
unicode-display_width (2.6.0)
|
|
||||||
word_wrap (1.0.0)
|
|
||||||
xcodeproj (1.27.0)
|
|
||||||
CFPropertyList (>= 2.3.3, < 4.0)
|
|
||||||
atomos (~> 0.1.3)
|
|
||||||
claide (>= 1.0.2, < 2.0)
|
|
||||||
colored2 (~> 3.1)
|
|
||||||
nanaimo (~> 0.4.0)
|
|
||||||
rexml (>= 3.3.6, < 4.0)
|
|
||||||
xcpretty (0.3.0)
|
|
||||||
rouge (~> 2.0.7)
|
|
||||||
xcpretty-travis-formatter (1.0.1)
|
|
||||||
xcpretty (~> 0.2, >= 0.0.7)
|
|
||||||
|
|
||||||
PLATFORMS
|
|
||||||
ruby
|
|
||||||
x86_64-linux
|
|
||||||
|
|
||||||
DEPENDENCIES
|
|
||||||
fastlane
|
|
||||||
|
|
||||||
BUNDLED WITH
|
|
||||||
2.5.16
|
|
|
@ -1,9 +1,3 @@
|
||||||
plugins {
|
|
||||||
id "com.android.application"
|
|
||||||
id "kotlin-android"
|
|
||||||
id "dev.flutter.flutter-gradle-plugin"
|
|
||||||
}
|
|
||||||
|
|
||||||
def localProperties = new Properties()
|
def localProperties = new Properties()
|
||||||
def localPropertiesFile = rootProject.file('local.properties')
|
def localPropertiesFile = rootProject.file('local.properties')
|
||||||
if (localPropertiesFile.exists()) {
|
if (localPropertiesFile.exists()) {
|
||||||
|
@ -12,6 +6,11 @@ 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')
|
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||||
if (flutterVersionCode == null) {
|
if (flutterVersionCode == null) {
|
||||||
flutterVersionCode = '1'
|
flutterVersionCode = '1'
|
||||||
|
@ -22,6 +21,9 @@ if (flutterVersionName == null) {
|
||||||
flutterVersionName = '1.0'
|
flutterVersionName = '1.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||||
|
|
||||||
def keystoreProperties = new Properties()
|
def keystoreProperties = new Properties()
|
||||||
def keystorePropertiesFile = rootProject.file('key.properties')
|
def keystorePropertiesFile = rootProject.file('key.properties')
|
||||||
if (keystorePropertiesFile.exists()) {
|
if (keystorePropertiesFile.exists()) {
|
||||||
|
@ -29,9 +31,7 @@ if (keystorePropertiesFile.exists()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 34
|
compileSdkVersion 33
|
||||||
|
|
||||||
namespace "de.varakh.fbmobile"
|
|
||||||
|
|
||||||
lintOptions {
|
lintOptions {
|
||||||
disable 'InvalidPackage'
|
disable 'InvalidPackage'
|
||||||
|
@ -39,8 +39,8 @@ android {
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "de.varakh.fbmobile"
|
applicationId "de.varakh.fbmobile"
|
||||||
minSdkVersion 30
|
minSdkVersion 19
|
||||||
targetSdkVersion 34
|
targetSdkVersion 33
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
|
@ -4,10 +4,7 @@
|
||||||
to allow setting breakpoints, to provide hot reload, etc.
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
-->
|
-->
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
|
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
|
||||||
|
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
|
|
|
@ -21,41 +21,6 @@
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.SEND" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:mimeType="text/*" />
|
|
||||||
</intent-filter>
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.SEND" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:mimeType="image/*" />
|
|
||||||
</intent-filter>
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:mimeType="image/*" />
|
|
||||||
</intent-filter>
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:mimeType="image/*" />
|
|
||||||
</intent-filter>
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:mimeType="video/*" />
|
|
||||||
</intent-filter>
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.SEND" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:mimeType="*/*" />
|
|
||||||
</intent-filter>
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:mimeType="*/*" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
</activity>
|
||||||
<!-- Don't delete the meta-data below.
|
<!-- Don't delete the meta-data below.
|
||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||||
|
@ -65,10 +30,7 @@
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
|
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
|
||||||
|
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
|
|
|
@ -4,10 +4,7 @@
|
||||||
to allow setting breakpoints, to provide hot reload, etc.
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
-->
|
-->
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
|
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
|
||||||
|
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
|
|
|
@ -1,3 +1,14 @@
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.android.tools.build:gradle:7.4.2'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
|
|
|
@ -11,11 +11,6 @@ platform :android do
|
||||||
sh("#{ENV['PWD']}/fastlane/buildAndroidProduction.sh")
|
sh("#{ENV['PWD']}/fastlane/buildAndroidProduction.sh")
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Build Production fdroid"
|
|
||||||
lane :build_production_fdroid do
|
|
||||||
sh("#{ENV['PWD']}/fastlane/buildAndroidProductionFdroid.sh")
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Build"
|
desc "Build"
|
||||||
lane :build do
|
lane :build do
|
||||||
sh("#{ENV['PWD']}/fastlane/buildAndroid.sh")
|
sh("#{ENV['PWD']}/fastlane/buildAndroid.sh")
|
||||||
|
|
|
@ -31,14 +31,6 @@ Build Debug
|
||||||
|
|
||||||
Build Production
|
Build Production
|
||||||
|
|
||||||
### android build_production_fdroid
|
|
||||||
|
|
||||||
```sh
|
|
||||||
[bundle exec] fastlane android build_production_fdroid
|
|
||||||
```
|
|
||||||
|
|
||||||
Build Production fdroid
|
|
||||||
|
|
||||||
### android build
|
### android build
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
#!/usr/bin/env sh
|
|
||||||
|
|
||||||
cd ../../;
|
|
||||||
flutter clean && \
|
|
||||||
flutter pub get &&
|
|
||||||
flutter packages pub run build_runner build --delete-conflicting-outputs;
|
|
||||||
|
|
||||||
flutter build apk --release;
|
|
||||||
flutter build apk --split-per-abi --release;
|
|
|
@ -1,6 +1,4 @@
|
||||||
agpVersion=8.7.2
|
|
||||||
kotlinVersion=1.7.10
|
|
||||||
|
|
||||||
org.gradle.jvmargs=-Xmx1536M
|
org.gradle.jvmargs=-Xmx1536M
|
||||||
|
android.enableR8=true
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
|
#Fri Jun 23 08:50:38 CEST 2017
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
|
||||||
networkTimeout=10000
|
|
||||||
validateDistributionUrl=true
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip
|
||||||
|
|
|
@ -1,25 +1,15 @@
|
||||||
pluginManagement {
|
include ':app'
|
||||||
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
|
|
||||||
}()
|
|
||||||
|
|
||||||
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
|
||||||
|
|
||||||
repositories {
|
def plugins = new Properties()
|
||||||
google()
|
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
|
||||||
mavenCentral()
|
if (pluginsFile.exists()) {
|
||||||
gradlePluginPortal()
|
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
plugins.each { name, path ->
|
||||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
|
||||||
id "com.android.application" version "${agpVersion}" apply false
|
include ":$name"
|
||||||
id "org.jetbrains.kotlin.android" version "${kotlinVersion}" apply false
|
project(":$name").projectDir = pluginDirectory
|
||||||
}
|
}
|
||||||
|
|
||||||
include ":app"
|
|
||||||
|
|
|
@ -126,6 +126,14 @@
|
||||||
"description": "Could not open '{link}'. Please ensure that you have an application installed which handles opening such link types."
|
"description": "Could not open '{link}'. Please ensure that you have an application installed which handles opening such link types."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"permission_service": {
|
||||||
|
"dialog": {
|
||||||
|
"title": "Storage permission",
|
||||||
|
"description": "Storage permission should be granted to the app so that it can work properly. Do you want to grant permission or ignore this message permanently in the future?",
|
||||||
|
"grant": "Grant",
|
||||||
|
"ignore": "Ignore"
|
||||||
|
}
|
||||||
|
},
|
||||||
"dialog": {
|
"dialog": {
|
||||||
"confirm": "OK",
|
"confirm": "OK",
|
||||||
"cancel": "Cancel"
|
"cancel": "Cancel"
|
||||||
|
|
|
@ -5,8 +5,8 @@ class RestServiceException extends ServiceException {
|
||||||
final int statusCode;
|
final int statusCode;
|
||||||
final dynamic responseBody;
|
final dynamic responseBody;
|
||||||
|
|
||||||
RestServiceException(this.statusCode, {this.responseBody, super.message = null})
|
RestServiceException(this.statusCode, {this.responseBody, String? message})
|
||||||
: super(code: ErrorCode.restError);
|
: super(code: ErrorCode.restError, message: message);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import '../services/dialog_service.dart';
|
||||||
class DialogManager extends StatefulWidget {
|
class DialogManager extends StatefulWidget {
|
||||||
final Widget? child;
|
final Widget? child;
|
||||||
|
|
||||||
const DialogManager({super.key, this.child});
|
const DialogManager({Key? key, this.child}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_DialogManagerState createState() => _DialogManagerState();
|
_DialogManagerState createState() => _DialogManagerState();
|
||||||
|
|
|
@ -11,7 +11,7 @@ import '../util/logger.dart';
|
||||||
class LifeCycleManager extends StatefulWidget {
|
class LifeCycleManager extends StatefulWidget {
|
||||||
final Widget? child;
|
final Widget? child;
|
||||||
|
|
||||||
const LifeCycleManager({super.key, this.child});
|
const LifeCycleManager({Key? key, this.child}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_LifeCycleManagerState createState() => _LifeCycleManagerState();
|
_LifeCycleManagerState createState() => _LifeCycleManagerState();
|
||||||
|
|
|
@ -1,100 +1,108 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io' show Platform;
|
|
||||||
|
|
||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:flutter_translate/flutter_translate.dart';
|
||||||
import 'package:logger/logger.dart';
|
import 'package:logger/logger.dart';
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
import '../../constants.dart';
|
import '../../constants.dart';
|
||||||
|
import '../../core/datamodels/dialog_response.dart';
|
||||||
|
import '../../core/services/dialog_service.dart';
|
||||||
import '../../core/services/stoppable_service.dart';
|
import '../../core/services/stoppable_service.dart';
|
||||||
import '../../core/util/logger.dart';
|
import '../../core/util/logger.dart';
|
||||||
|
import '../../locator.dart';
|
||||||
|
import 'storage_service.dart';
|
||||||
|
|
||||||
class PermissionService extends StoppableService {
|
class PermissionService extends StoppableService {
|
||||||
final Logger _logger = getLogger();
|
final Logger _logger = getLogger();
|
||||||
|
final DialogService _dialogService = locator<DialogService>();
|
||||||
|
final StorageService _storageService = locator<StorageService>();
|
||||||
|
|
||||||
Timer? _serviceCheckTimer;
|
Timer? _serviceCheckTimer;
|
||||||
|
|
||||||
|
PermissionStatus? _permissionStatus;
|
||||||
|
|
||||||
|
bool _permanentlyIgnored = false;
|
||||||
bool _devicePermissionDialogActive = false;
|
bool _devicePermissionDialogActive = false;
|
||||||
|
bool _ownPermissionDialogActive = false;
|
||||||
|
|
||||||
bool _deviceInformationInitialized = false;
|
PermissionService() {
|
||||||
bool _useStoragePermission = true;
|
_devicePermissionDialogActive = true;
|
||||||
|
|
||||||
PermissionService();
|
Permission.storage.request().then((status) {
|
||||||
|
_permissionStatus = status;
|
||||||
|
if (PermissionStatus.permanentlyDenied == status) {
|
||||||
|
_permanentlyIgnored = true;
|
||||||
|
}
|
||||||
|
}).whenComplete(() {
|
||||||
|
_logger.d('Initial device request permission finished');
|
||||||
|
_devicePermissionDialogActive = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Future checkEnabledAndPermission() async {
|
Future checkEnabledAndPermission() async {
|
||||||
|
if (_permanentlyIgnored) {
|
||||||
|
await _storageService.storeStoragePermissionDialogIgnored();
|
||||||
|
_permanentlyIgnored = false;
|
||||||
|
_logger.d('Set permanently ignored permission request');
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
if (_devicePermissionDialogActive) {
|
if (_devicePermissionDialogActive) {
|
||||||
_logger.d('Device permission dialog active, skipping');
|
_logger.d('Device permission dialog active, skipping');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool allGranted = false;
|
if (_ownPermissionDialogActive) {
|
||||||
bool anyPermanentlyDenied = false;
|
_logger.d('Own permission dialog already active, skipping');
|
||||||
|
return;
|
||||||
// Since Android compileSdk >= 33, "storage" is deprecated
|
|
||||||
// Instead, request access to all of
|
|
||||||
// - Permission.photos
|
|
||||||
// - Permission.videos
|
|
||||||
// - Permission.audio
|
|
||||||
//
|
|
||||||
// For iOS and Android < 33, keep using "storage"
|
|
||||||
if (_useStoragePermission) {
|
|
||||||
PermissionStatus storagePermission = await Permission.storage.status;
|
|
||||||
allGranted = PermissionStatus.granted == storagePermission;
|
|
||||||
anyPermanentlyDenied =
|
|
||||||
PermissionStatus.permanentlyDenied == storagePermission;
|
|
||||||
} else {
|
|
||||||
PermissionStatus photosPermission = await Permission.photos.status;
|
|
||||||
PermissionStatus videosPermission = await Permission.videos.status;
|
|
||||||
PermissionStatus audioPermission = await Permission.audio.status;
|
|
||||||
|
|
||||||
allGranted = PermissionStatus.granted == photosPermission &&
|
|
||||||
PermissionStatus.granted == videosPermission &&
|
|
||||||
PermissionStatus.granted == audioPermission;
|
|
||||||
anyPermanentlyDenied =
|
|
||||||
PermissionStatus.permanentlyDenied == photosPermission ||
|
|
||||||
PermissionStatus.permanentlyDenied == videosPermission ||
|
|
||||||
PermissionStatus.permanentlyDenied == audioPermission;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// show warning to user to manually handle, don't enforce it over and over again
|
var ignoredDialog =
|
||||||
if (anyPermanentlyDenied) {
|
await _storageService.hasStoragePermissionDialogIgnored();
|
||||||
_logger.w(
|
|
||||||
"At least one required permission has been denied permanently, stopping service");
|
if (ignoredDialog) {
|
||||||
|
_logger.d('Permanently ignored permission request, skipping');
|
||||||
stop();
|
stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// all good, stop the permission service
|
_permissionStatus = await Permission.storage.status;
|
||||||
if (allGranted) {
|
if (_permissionStatus != PermissionStatus.granted) {
|
||||||
_logger.d("All permissions have been granted, stopping service");
|
if (_permissionStatus == PermissionStatus.permanentlyDenied) {
|
||||||
stop();
|
await _storageService.storeStoragePermissionDialogIgnored();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// not all have been granted, show OS dialog
|
_ownPermissionDialogActive = true;
|
||||||
_logger.d(
|
DialogResponse response = await _dialogService.showConfirmationDialog(
|
||||||
"Not all permissions have been granted yet, initializing permission dialog");
|
title: translate('permission_service.dialog.title'),
|
||||||
_devicePermissionDialogActive = true;
|
description: translate('permission_service.dialog.description'),
|
||||||
|
buttonTitleAccept: translate('permission_service.dialog.grant'),
|
||||||
|
buttonTitleDeny: translate('permission_service.dialog.ignore'));
|
||||||
|
|
||||||
if (_useStoragePermission) {
|
if (!response.confirmed!) {
|
||||||
await [Permission.storage].request().whenComplete(() {
|
await _storageService.storeStoragePermissionDialogIgnored();
|
||||||
_logger.d('Device request permission finished');
|
} else {
|
||||||
_devicePermissionDialogActive = false;
|
_devicePermissionDialogActive = true;
|
||||||
});
|
Permission.storage.request().then((status) async {
|
||||||
|
if (PermissionStatus.permanentlyDenied == status) {
|
||||||
|
await _storageService.storeStoragePermissionDialogIgnored();
|
||||||
|
}
|
||||||
|
}).whenComplete(() {
|
||||||
|
_logger.d('Device request permission finished');
|
||||||
|
_devicePermissionDialogActive = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_ownPermissionDialogActive = false;
|
||||||
} else {
|
} else {
|
||||||
await [Permission.photos, Permission.videos, Permission.audio]
|
await _storageService.storeStoragePermissionDialogIgnored();
|
||||||
.request()
|
|
||||||
.whenComplete(() {
|
|
||||||
_logger.d('Device request permission finished');
|
|
||||||
_devicePermissionDialogActive = false;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future start() async {
|
Future start() async {
|
||||||
super.start();
|
super.start();
|
||||||
await _determineDeviceInfo();
|
|
||||||
await checkEnabledAndPermission();
|
await checkEnabledAndPermission();
|
||||||
|
|
||||||
_serviceCheckTimer = Timer.periodic(
|
_serviceCheckTimer = Timer.periodic(
|
||||||
|
@ -116,29 +124,6 @@ class PermissionService extends StoppableService {
|
||||||
_logger.d('PermissionService stopped');
|
_logger.d('PermissionService stopped');
|
||||||
}
|
}
|
||||||
|
|
||||||
Future _determineDeviceInfo() async {
|
|
||||||
if (_deviceInformationInitialized) {
|
|
||||||
_logger.d('Device information already initialized, skipping');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
|
|
||||||
if (Platform.isAndroid) {
|
|
||||||
final androidInfo = await deviceInfoPlugin.androidInfo;
|
|
||||||
if (androidInfo.version.sdkInt >= 33) {
|
|
||||||
_useStoragePermission = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_useStoragePermission) {
|
|
||||||
_logger.d('Device requires [storage] permission');
|
|
||||||
} else {
|
|
||||||
_logger.d('Device requires [photos,videos,audio] permission');
|
|
||||||
}
|
|
||||||
|
|
||||||
_deviceInformationInitialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _removeServiceCheckTimer() {
|
void _removeServiceCheckTimer() {
|
||||||
if (_serviceCheckTimer != null) {
|
if (_serviceCheckTimer != null) {
|
||||||
_serviceCheckTimer!.cancel();
|
_serviceCheckTimer!.cancel();
|
||||||
|
|
|
@ -7,6 +7,8 @@ import '../models/session.dart';
|
||||||
class StorageService {
|
class StorageService {
|
||||||
static const _sessionKey = 'session';
|
static const _sessionKey = 'session';
|
||||||
static const _lastUrlKey = 'last_url';
|
static const _lastUrlKey = 'last_url';
|
||||||
|
static const _storagePermissionDialogIgnoredKey =
|
||||||
|
'storage_permission_ignored';
|
||||||
|
|
||||||
Future<bool> storeLastUrl(String url) {
|
Future<bool> storeLastUrl(String url) {
|
||||||
return _store(_lastUrlKey, url);
|
return _store(_lastUrlKey, url);
|
||||||
|
@ -37,6 +39,14 @@ class StorageService {
|
||||||
return _remove(_sessionKey);
|
return _remove(_sessionKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> storeStoragePermissionDialogIgnored() {
|
||||||
|
return _store(_storagePermissionDialogIgnoredKey, true.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> hasStoragePermissionDialogIgnored() {
|
||||||
|
return _exists(_storagePermissionDialogIgnoredKey);
|
||||||
|
}
|
||||||
|
|
||||||
Future<bool> _exists(String key) async {
|
Future<bool> _exists(String key) async {
|
||||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
return prefs.containsKey(key);
|
return prefs.containsKey(key);
|
||||||
|
|
|
@ -108,7 +108,7 @@ class HistoryModel extends BaseModel {
|
||||||
} else {
|
} else {
|
||||||
errorMessage = translate('app.unknown_error');
|
errorMessage = translate('app.unknown_error');
|
||||||
setStateView(ViewState.idle);
|
setStateView(ViewState.idle);
|
||||||
_logger.e('An unknown error occurred', error: e);
|
_logger.e('An unknown error occurred', e);
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ class HistoryModel extends BaseModel {
|
||||||
} else {
|
} else {
|
||||||
errorMessage = translate('app.unknown_error');
|
errorMessage = translate('app.unknown_error');
|
||||||
setStateView(ViewState.idle);
|
setStateView(ViewState.idle);
|
||||||
_logger.e('An unknown error occurred', error: e);
|
_logger.e('An unknown error occurred', e);
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,7 +163,7 @@ class LoginModel extends BaseModel {
|
||||||
errorMessage = translate('app.unknown_error');
|
errorMessage = translate('app.unknown_error');
|
||||||
_sessionService.logout();
|
_sessionService.logout();
|
||||||
setStateView(ViewState.idle);
|
setStateView(ViewState.idle);
|
||||||
_logger.e('An unknown error occurred', error: e);
|
_logger.e('An unknown error occurred', e);
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ class ProfileModel extends BaseModel {
|
||||||
setStateBoolValue(_configurationButtonLoading, false);
|
setStateBoolValue(_configurationButtonLoading, false);
|
||||||
_sessionService.logout();
|
_sessionService.logout();
|
||||||
setStateBoolValue(_configurationButtonLoading, false);
|
setStateBoolValue(_configurationButtonLoading, false);
|
||||||
_logger.e('An unknown error occurred', error: e);
|
_logger.e('An unknown error occurred', e);
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import 'package:fbmobile/core/services/permission_service.dart';
|
|
||||||
import 'package:flutter_translate/flutter_translate.dart';
|
import 'package:flutter_translate/flutter_translate.dart';
|
||||||
|
|
||||||
import '../../locator.dart';
|
import '../../locator.dart';
|
||||||
|
@ -10,18 +9,16 @@ import 'base_model.dart';
|
||||||
|
|
||||||
class StartUpViewModel extends BaseModel {
|
class StartUpViewModel extends BaseModel {
|
||||||
final SessionService _sessionService = locator<SessionService>();
|
final SessionService _sessionService = locator<SessionService>();
|
||||||
final PermissionService _permissionService = locator<PermissionService>();
|
|
||||||
final NavigationService _navigationService = locator<NavigationService>();
|
final NavigationService _navigationService = locator<NavigationService>();
|
||||||
|
|
||||||
Future handleStartUpLogic() async {
|
Future handleStartUpLogic() async {
|
||||||
setStateView(ViewState.busy);
|
setStateView(ViewState.busy);
|
||||||
setStateMessage(translate('startup.init'));
|
setStateMessage(translate('startup.init'));
|
||||||
await Future.delayed(const Duration(milliseconds: 100));
|
await Future.delayed(const Duration(milliseconds: 150));
|
||||||
|
|
||||||
setStateMessage(translate('startup.start_services'));
|
setStateMessage(translate('startup.start_services'));
|
||||||
await _sessionService.start();
|
await _sessionService.start();
|
||||||
await _permissionService.start();
|
await Future.delayed(const Duration(milliseconds: 150));
|
||||||
await Future.delayed(const Duration(milliseconds: 100));
|
|
||||||
|
|
||||||
_navigationService.navigateAndReplaceTo(HomeView.routeName);
|
_navigationService.navigateAndReplaceTo(HomeView.routeName);
|
||||||
|
|
||||||
|
|
|
@ -152,9 +152,9 @@ class UploadModel extends BaseModel {
|
||||||
))
|
))
|
||||||
?.files;
|
?.files;
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
_logger.e('Unsupported operation', error: e);
|
_logger.e('Unsupported operation', e);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
_logger.e('An unknown error occurred', error: ex);
|
_logger.e('An unknown error occurred', ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadingPath = false;
|
loadingPath = false;
|
||||||
|
@ -238,7 +238,7 @@ class UploadModel extends BaseModel {
|
||||||
errorMessage = translate('app.unknown_error');
|
errorMessage = translate('app.unknown_error');
|
||||||
setStateMessage(null);
|
setStateMessage(null);
|
||||||
setStateView(ViewState.idle);
|
setStateView(ViewState.idle);
|
||||||
_logger.e('An unknown error occurred', error: e);
|
_logger.e('An unknown error occurred', e);
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,9 +91,7 @@ class HistoryView extends StatelessWidget {
|
||||||
content: Text(translate('history.copy_link.copied')),
|
content: Text(translate('history.copy_link.copied')),
|
||||||
duration: const Duration(seconds: 10),
|
duration: const Duration(seconds: 10),
|
||||||
);
|
);
|
||||||
if (context.mounted) {
|
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
@ -53,26 +53,24 @@ class ProfileView extends StatelessWidget {
|
||||||
UIHelper.verticalSpaceMedium(),
|
UIHelper.verticalSpaceMedium(),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 25.0, right: 25.0),
|
padding: const EdgeInsets.only(left: 25.0, right: 25.0),
|
||||||
child: ElevatedButton.icon(
|
child: model.configLoading
|
||||||
icon: model.configLoading
|
? Center(
|
||||||
? Container(
|
child: Column(
|
||||||
width: 24,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
height: 24,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
padding: const EdgeInsets.all(2.0),
|
children: [
|
||||||
child: const CircularProgressIndicator(
|
const CircularProgressIndicator(),
|
||||||
color: blueColor,
|
Text(translate('profile.show_config_loading')),
|
||||||
strokeWidth: 3,
|
],
|
||||||
),
|
))
|
||||||
)
|
: ElevatedButton.icon(
|
||||||
: const Icon(Icons.settings, color: blueColor),
|
icon: const Icon(Icons.settings, color: blueColor),
|
||||||
label: Text(
|
label: Text(
|
||||||
model.configLoading
|
translate('profile.show_config'),
|
||||||
? translate('profile.show_config_loading')
|
),
|
||||||
: translate('profile.show_config'),
|
onPressed: () async {
|
||||||
),
|
await model.showConfig(url);
|
||||||
onPressed: () async {
|
})),
|
||||||
await model.showConfig(url);
|
|
||||||
})),
|
|
||||||
UIHelper.verticalSpaceMedium(),
|
UIHelper.verticalSpaceMedium(),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 25.0, right: 25.0),
|
padding: const EdgeInsets.only(left: 25.0, right: 25.0),
|
||||||
|
|
|
@ -151,10 +151,8 @@ class UploadView extends StatelessWidget {
|
||||||
duration:
|
duration:
|
||||||
const Duration(seconds: 10),
|
const Duration(seconds: 10),
|
||||||
);
|
);
|
||||||
if (context.mounted) {
|
ScaffoldMessenger.of(context)
|
||||||
ScaffoldMessenger.of(context)
|
.showSnackBar(snackBar);
|
||||||
.showSnackBar(snackBar);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,11 +7,12 @@ class MyAppBar extends AppBar {
|
||||||
static final List<Widget> aboutDisabledWidgets = [];
|
static final List<Widget> aboutDisabledWidgets = [];
|
||||||
|
|
||||||
MyAppBar(
|
MyAppBar(
|
||||||
{super.key,
|
{Key? key,
|
||||||
required Widget title,
|
required Widget title,
|
||||||
List<Widget>? actionWidgets,
|
List<Widget>? actionWidgets,
|
||||||
bool enableAbout = true})
|
bool enableAbout = true})
|
||||||
: super(
|
: super(
|
||||||
|
key: key,
|
||||||
title: Row(children: <Widget>[title]),
|
title: Row(children: <Widget>[title]),
|
||||||
actions: _renderIconButtons(actionWidgets, enableAbout));
|
actions: _renderIconButtons(actionWidgets, enableAbout));
|
||||||
|
|
||||||
|
|
501
pubspec.lock
501
pubspec.lock
File diff suppressed because it is too large
Load diff
49
pubspec.yaml
49
pubspec.yaml
|
@ -11,47 +11,46 @@ description: A mobile client for FileBin.
|
||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||||
# Read more about iOS versioning at
|
# Read more about iOS versioning at
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
version: 1.6.4+22
|
version: 1.6.1+19
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.5.0 <4.0.0'
|
sdk: '>=2.19.4 <3.0.0'
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
cupertino_icons: 1.0.8
|
cupertino_icons: 1.0.5
|
||||||
flutter_localizations:
|
flutter_localizations:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_translate: 4.1.0
|
flutter_translate: 4.0.4
|
||||||
provider: 6.1.2
|
provider: 6.0.5
|
||||||
stacked: 3.4.3
|
stacked: 3.3.0
|
||||||
get_it: 7.7.0
|
get_it: 7.6.0
|
||||||
logger: 2.4.0
|
logger: 1.3.0
|
||||||
shared_preferences: 2.3.2
|
shared_preferences: 2.1.1
|
||||||
http: 1.2.2
|
http: 0.13.6
|
||||||
validators: 3.0.0
|
validators: 3.0.0
|
||||||
flutter_linkify: 6.0.0
|
flutter_linkify: 6.0.0
|
||||||
url_launcher: 6.3.1
|
url_launcher: 6.1.11
|
||||||
expandable: 5.0.1
|
expandable: 5.0.1
|
||||||
share_plus: 10.1.1
|
share_plus: 7.0.1
|
||||||
file_picker: 8.1.3
|
file_picker: 5.3.1
|
||||||
clipboard: 0.1.3
|
clipboard: 0.1.3
|
||||||
permission_handler: 11.3.1
|
permission_handler: 10.2.0
|
||||||
package_info_plus: 8.1.0
|
package_info_plus: 4.0.1
|
||||||
json_annotation: 4.9.0
|
json_annotation: ^4.8.1
|
||||||
dynamic_color: 1.7.0
|
dynamic_color: 1.6.5
|
||||||
intl: 0.19.0
|
intl: 0.18.0
|
||||||
path: 1.9.0
|
path: 1.8.3
|
||||||
flutter_sharing_intent: 1.1.1
|
flutter_sharing_intent: 1.0.6
|
||||||
device_info_plus: 11.1.0
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
build_runner: 2.4.13
|
build_runner: 2.4.4
|
||||||
built_value_generator: 8.9.2
|
built_value_generator: 8.6.0
|
||||||
json_serializable: 6.8.0
|
json_serializable: 6.7.0
|
||||||
flutter_lints: 5.0.0
|
flutter_lints: 2.0.1
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://www.dartlang.org/tools/pub/pubspec
|
# following page: https://www.dartlang.org/tools/pub/pubspec
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
|
||||||
"extends": [
|
|
||||||
"config:recommended",
|
|
||||||
":rebaseStalePrs",
|
|
||||||
":ignoreUnstable",
|
|
||||||
"group:monorepos",
|
|
||||||
"group:recommended"
|
|
||||||
],
|
|
||||||
"prConcurrentLimit": 0,
|
|
||||||
"schedule": [
|
|
||||||
"monthly"
|
|
||||||
],
|
|
||||||
"ignorePaths": [
|
|
||||||
"android/**",
|
|
||||||
"ios/**"
|
|
||||||
],
|
|
||||||
"ignoreDeps": [
|
|
||||||
"intl",
|
|
||||||
"path"
|
|
||||||
],
|
|
||||||
"packageRules": [
|
|
||||||
{
|
|
||||||
"matchUpdateTypes": [
|
|
||||||
"minor"
|
|
||||||
],
|
|
||||||
"groupName": "all minor dependencies",
|
|
||||||
"groupSlug": "all-minor-deps"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"matchUpdateTypes": [
|
|
||||||
"patch"
|
|
||||||
],
|
|
||||||
"groupName": "all patch dependencies",
|
|
||||||
"groupSlug": "all-patch-deps"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
Loading…
Reference in a new issue