Compare commits
157 commits
Author | SHA1 | Date | |
---|---|---|---|
ae2a6b8b32 | |||
dce3c916a2 | |||
58141fe646 | |||
dd5abc48f9 | |||
bf1f1e3295 | |||
e7463ffaef | |||
ae454abb3a | |||
34bcd2ee92 | |||
d2485a91cd | |||
e8c8808c0e | |||
b544003941 | |||
5668c15547 | |||
7f145f6960 | |||
d0dd798008 | |||
f16ee08079 | |||
a4a3c2e5dc | |||
a5e9597207 | |||
f460c68339 | |||
c7af6a874d | |||
e0973735d8 | |||
dc715e38d1 | |||
eb1d949af8 | |||
4a715aba48 | |||
c48c16d63d | |||
57db10e912 | |||
a4defff982 | |||
3ae2c37813 | |||
d9b33feac9 | |||
941b7c81ad | |||
5bc02638f7 | |||
477e557d31 | |||
c917e478a6 | |||
8b96610fa6 | |||
df40808bd7 | |||
dfc5772b93 | |||
3d6ae1a9ef | |||
e49dd86347 | |||
4cd6165d9b | |||
e661171fd2 | |||
c99df89cb0 | |||
03d61dcdd0 | |||
f2d1083620 | |||
b5694ae9c6 | |||
9dd84b20a9 | |||
8bb310fb40 | |||
47987b8dad | |||
3d68dcefab | |||
b51131de8f | |||
7e871bb4b1 | |||
88b9d81bc2 | |||
7c7befe071 | |||
2461a02f9d | |||
15104d7e40 | |||
733f09baab | |||
1758eeed18 | |||
c9764e780b | |||
3754d71dec | |||
8904d49eb2 | |||
0e7bc55bef | |||
089d07846d | |||
3f64f86acf | |||
7c91d8b6ca | |||
df1b038782 | |||
c9ef125abb | |||
5a8750b877 | |||
8c10e42c0f | |||
96d8cbea99 | |||
685b140135 | |||
f51e781a9f | |||
16c1a597fc | |||
71ac72a6cc | |||
0bc3ae1da8 | |||
fc5b8783d3 | |||
5492fed0b5 | |||
30810868b2 | |||
a889a6fbee | |||
36e5bcab1f | |||
3b06c2b80b | |||
e4cfa81672 | |||
2837054383 | |||
4deb9b92cb | |||
b0edda0432 | |||
886632957d | |||
264609dff3 | |||
d87796f47b | |||
42f40d52d2 | |||
292660a970 | |||
51e2c476c7 | |||
44cc8bac28 | |||
9b571fb1a4 | |||
d63ef288eb | |||
549b218922 | |||
f61c5a4a1b | |||
a06bbf6751 | |||
e980f1ae53 | |||
66a5f4e9af | |||
39b1465efc | |||
22d096ae43 | |||
08d935284d | |||
6b87873cc7 | |||
41987331b0 | |||
f19d23a757 | |||
67076779a3 | |||
6d302c4392 | |||
53cd587a42 | |||
769dd7e513 | |||
a3ee146e25 | |||
5e9947969e | |||
689c8b4408 | |||
7cee219b19 | |||
803cd11cc4 | |||
a99662af3c | |||
3d11fde4e9 | |||
43cb6472f2 | |||
67dafa615f | |||
fc0fe31b70 | |||
0e4dcbde22 | |||
65a0a294a6 | |||
548d02362b | |||
c50e9ec7ba | |||
e5518b4ade | |||
0b093302ec | |||
4114feb56e | |||
d8c9027509 | |||
e1075f5725 | |||
b49f10c875 | |||
494420cbd3 | |||
aedc7f2bbb | |||
9ac363070b | |||
580099856f | |||
d56d717de0 | |||
3cf96ad5ab | |||
26d0e0851b | |||
c772d950e2 | |||
0630035e45 | |||
3fb46fc766 | |||
53c65ce54f | |||
9a1db51f23 | |||
664b734544 | |||
0e69e904b4 | |||
09b608a168 | |||
091e344831 | |||
0f9e8b398f | |||
88d85257a7 | |||
06566d3d6e | |||
35bdd06f72 | |||
e59164e803 | |||
eec38b455c | |||
ee6230399a | |||
31d91bafc1 | |||
82f9ab5535 | |||
66493cff91 | |||
210c3e7aa4 | |||
d6b645112e | |||
713d8f57be | |||
bc777d4826 | |||
ad9a3a15f5 |
36 changed files with 880 additions and 410 deletions
21
.drone.yml
21
.drone.yml
|
@ -1,21 +0,0 @@
|
|||
---
|
||||
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
|
21
.forgejo/workflows/build.yaml
Normal file
21
.forgejo/workflows/build.yaml
Normal file
|
@ -0,0 +1,21 @@
|
|||
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,6 +1,7 @@
|
|||
# Miscellaneous
|
||||
*.class
|
||||
*.lock
|
||||
!Gemfile.lock
|
||||
!pubspec.lock
|
||||
*.log
|
||||
*.pyc
|
||||
|
|
15
CHANGELOG.md
15
CHANGELOG.md
|
@ -1,5 +1,20 @@
|
|||
# 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
|
||||
* Updated internal dependencies
|
||||
|
||||
|
|
31
README.md
31
README.md
|
@ -2,7 +2,8 @@
|
|||
|
||||
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).
|
||||
Available on the [Play Store](https://play.google.com/store/apps/details?id=de.varakh.fbmobile) and
|
||||
[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)**.
|
||||
Other repositories are mirrors and pull requests, issues, and planning are managed there.
|
||||
|
@ -94,7 +95,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.
|
||||
|
||||
#### Usage
|
||||
#### Usage / doing the actual release
|
||||
|
||||
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
|
||||
|
@ -104,13 +105,37 @@ following to build for Android `fastlane android build`.
|
|||
|
||||
##### Android
|
||||
|
||||
Use `fastlane android beta` to build and upload a new beta version to the Play Store.
|
||||
It's recommended you set up `fastlane` via `bundler` (you need this to be installed on your machine).
|
||||
|
||||
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
|
||||
|
||||
For iOS you need to execute `fastlane ios build` before uploading to testflight with
|
||||
`fastlane ios beta`.
|
||||
|
||||
Probably do the same Ruby/fastlane setup as mentioned under the _Android_ section.
|
||||
|
||||
### Release manually (not recommended)
|
||||
|
||||
See the following links on how to setup:
|
||||
|
|
2
android/.gitignore
vendored
2
android/.gitignore
vendored
|
@ -5,3 +5,5 @@ gradle-wrapper.jar
|
|||
/gradlew.bat
|
||||
/local.properties
|
||||
GeneratedPluginRegistrant.java
|
||||
.bundle
|
||||
vendor/
|
||||
|
|
222
android/Gemfile.lock
Normal file
222
android/Gemfile.lock
Normal file
|
@ -0,0 +1,222 @@
|
|||
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,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,9 +22,6 @@ if (flutterVersionName == null) {
|
|||
flutterVersionName = '1.0'
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||
|
||||
def keystoreProperties = new Properties()
|
||||
def keystorePropertiesFile = rootProject.file('key.properties')
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
|
@ -31,7 +29,9 @@ if (keystorePropertiesFile.exists()) {
|
|||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 33
|
||||
compileSdkVersion 34
|
||||
|
||||
namespace "de.varakh.fbmobile"
|
||||
|
||||
lintOptions {
|
||||
disable 'InvalidPackage'
|
||||
|
@ -39,8 +39,8 @@ android {
|
|||
|
||||
defaultConfig {
|
||||
applicationId "de.varakh.fbmobile"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 33
|
||||
minSdkVersion 30
|
||||
targetSdkVersion 34
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
|
|
@ -4,7 +4,10 @@
|
|||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
|
||||
<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>
|
||||
<intent>
|
||||
|
|
|
@ -21,6 +21,41 @@
|
|||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</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>
|
||||
<!-- Don't delete the meta-data below.
|
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||
|
@ -30,7 +65,10 @@
|
|||
</application>
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
|
||||
<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>
|
||||
<intent>
|
||||
|
|
|
@ -4,7 +4,10 @@
|
|||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
|
||||
<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>
|
||||
<intent>
|
||||
|
|
|
@ -1,14 +1,3 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.4.2'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
|
|
|
@ -11,6 +11,11 @@ platform :android do
|
|||
sh("#{ENV['PWD']}/fastlane/buildAndroidProduction.sh")
|
||||
end
|
||||
|
||||
desc "Build Production fdroid"
|
||||
lane :build_production_fdroid do
|
||||
sh("#{ENV['PWD']}/fastlane/buildAndroidProductionFdroid.sh")
|
||||
end
|
||||
|
||||
desc "Build"
|
||||
lane :build do
|
||||
sh("#{ENV['PWD']}/fastlane/buildAndroid.sh")
|
||||
|
|
|
@ -31,6 +31,14 @@ Build Debug
|
|||
|
||||
Build Production
|
||||
|
||||
### android build_production_fdroid
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane android build_production_fdroid
|
||||
```
|
||||
|
||||
Build Production fdroid
|
||||
|
||||
### android build
|
||||
|
||||
```sh
|
||||
|
|
9
android/fastlane/buildAndroidProductionFdroid.sh
Executable file
9
android/fastlane/buildAndroidProductionFdroid.sh
Executable file
|
@ -0,0 +1,9 @@
|
|||
#!/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,4 +1,6 @@
|
|||
agpVersion=8.7.2
|
||||
kotlinVersion=1.7.10
|
||||
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#Fri Jun 23 08:50:38 CEST 2017
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip
|
||||
|
|
|
@ -1,15 +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 flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
|
||||
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
||||
|
||||
def plugins = new Properties()
|
||||
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
|
||||
if (pluginsFile.exists()) {
|
||||
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
plugins.each { name, path ->
|
||||
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
|
||||
include ":$name"
|
||||
project(":$name").projectDir = pluginDirectory
|
||||
plugins {
|
||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||
id "com.android.application" version "${agpVersion}" apply false
|
||||
id "org.jetbrains.kotlin.android" version "${kotlinVersion}" apply false
|
||||
}
|
||||
|
||||
include ":app"
|
||||
|
|
|
@ -126,14 +126,6 @@
|
|||
"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": {
|
||||
"confirm": "OK",
|
||||
"cancel": "Cancel"
|
||||
|
|
|
@ -5,8 +5,8 @@ class RestServiceException extends ServiceException {
|
|||
final int statusCode;
|
||||
final dynamic responseBody;
|
||||
|
||||
RestServiceException(this.statusCode, {this.responseBody, String? message})
|
||||
: super(code: ErrorCode.restError, message: message);
|
||||
RestServiceException(this.statusCode, {this.responseBody, super.message = null})
|
||||
: super(code: ErrorCode.restError);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
|
|
|
@ -8,7 +8,7 @@ import '../services/dialog_service.dart';
|
|||
class DialogManager extends StatefulWidget {
|
||||
final Widget? child;
|
||||
|
||||
const DialogManager({Key? key, this.child}) : super(key: key);
|
||||
const DialogManager({super.key, this.child});
|
||||
|
||||
@override
|
||||
_DialogManagerState createState() => _DialogManagerState();
|
||||
|
|
|
@ -11,7 +11,7 @@ import '../util/logger.dart';
|
|||
class LifeCycleManager extends StatefulWidget {
|
||||
final Widget? child;
|
||||
|
||||
const LifeCycleManager({Key? key, this.child}) : super(key: key);
|
||||
const LifeCycleManager({super.key, this.child});
|
||||
|
||||
@override
|
||||
_LifeCycleManagerState createState() => _LifeCycleManagerState();
|
||||
|
|
|
@ -1,108 +1,100 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io' show Platform;
|
||||
|
||||
import 'package:flutter_translate/flutter_translate.dart';
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:logger/logger.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
import '../../constants.dart';
|
||||
import '../../core/datamodels/dialog_response.dart';
|
||||
import '../../core/services/dialog_service.dart';
|
||||
import '../../core/services/stoppable_service.dart';
|
||||
import '../../core/util/logger.dart';
|
||||
import '../../locator.dart';
|
||||
import 'storage_service.dart';
|
||||
|
||||
class PermissionService extends StoppableService {
|
||||
final Logger _logger = getLogger();
|
||||
final DialogService _dialogService = locator<DialogService>();
|
||||
final StorageService _storageService = locator<StorageService>();
|
||||
|
||||
Timer? _serviceCheckTimer;
|
||||
|
||||
PermissionStatus? _permissionStatus;
|
||||
|
||||
bool _permanentlyIgnored = false;
|
||||
bool _devicePermissionDialogActive = false;
|
||||
bool _ownPermissionDialogActive = false;
|
||||
|
||||
PermissionService() {
|
||||
_devicePermissionDialogActive = true;
|
||||
bool _deviceInformationInitialized = false;
|
||||
bool _useStoragePermission = true;
|
||||
|
||||
Permission.storage.request().then((status) {
|
||||
_permissionStatus = status;
|
||||
if (PermissionStatus.permanentlyDenied == status) {
|
||||
_permanentlyIgnored = true;
|
||||
}
|
||||
}).whenComplete(() {
|
||||
_logger.d('Initial device request permission finished');
|
||||
_devicePermissionDialogActive = false;
|
||||
});
|
||||
}
|
||||
PermissionService();
|
||||
|
||||
Future checkEnabledAndPermission() async {
|
||||
if (_permanentlyIgnored) {
|
||||
await _storageService.storeStoragePermissionDialogIgnored();
|
||||
_permanentlyIgnored = false;
|
||||
_logger.d('Set permanently ignored permission request');
|
||||
stop();
|
||||
}
|
||||
|
||||
if (_devicePermissionDialogActive) {
|
||||
_logger.d('Device permission dialog active, skipping');
|
||||
return;
|
||||
}
|
||||
|
||||
if (_ownPermissionDialogActive) {
|
||||
_logger.d('Own permission dialog already active, skipping');
|
||||
return;
|
||||
bool allGranted = false;
|
||||
bool anyPermanentlyDenied = false;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
var ignoredDialog =
|
||||
await _storageService.hasStoragePermissionDialogIgnored();
|
||||
|
||||
if (ignoredDialog) {
|
||||
_logger.d('Permanently ignored permission request, skipping');
|
||||
// show warning to user to manually handle, don't enforce it over and over again
|
||||
if (anyPermanentlyDenied) {
|
||||
_logger.w(
|
||||
"At least one required permission has been denied permanently, stopping service");
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
_permissionStatus = await Permission.storage.status;
|
||||
if (_permissionStatus != PermissionStatus.granted) {
|
||||
if (_permissionStatus == PermissionStatus.permanentlyDenied) {
|
||||
await _storageService.storeStoragePermissionDialogIgnored();
|
||||
return;
|
||||
}
|
||||
// all good, stop the permission service
|
||||
if (allGranted) {
|
||||
_logger.d("All permissions have been granted, stopping service");
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
_ownPermissionDialogActive = true;
|
||||
DialogResponse response = await _dialogService.showConfirmationDialog(
|
||||
title: translate('permission_service.dialog.title'),
|
||||
description: translate('permission_service.dialog.description'),
|
||||
buttonTitleAccept: translate('permission_service.dialog.grant'),
|
||||
buttonTitleDeny: translate('permission_service.dialog.ignore'));
|
||||
// not all have been granted, show OS dialog
|
||||
_logger.d(
|
||||
"Not all permissions have been granted yet, initializing permission dialog");
|
||||
_devicePermissionDialogActive = true;
|
||||
|
||||
if (!response.confirmed!) {
|
||||
await _storageService.storeStoragePermissionDialogIgnored();
|
||||
} else {
|
||||
_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;
|
||||
if (_useStoragePermission) {
|
||||
await [Permission.storage].request().whenComplete(() {
|
||||
_logger.d('Device request permission finished');
|
||||
_devicePermissionDialogActive = false;
|
||||
});
|
||||
} else {
|
||||
await _storageService.storeStoragePermissionDialogIgnored();
|
||||
await [Permission.photos, Permission.videos, Permission.audio]
|
||||
.request()
|
||||
.whenComplete(() {
|
||||
_logger.d('Device request permission finished');
|
||||
_devicePermissionDialogActive = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future start() async {
|
||||
super.start();
|
||||
await _determineDeviceInfo();
|
||||
await checkEnabledAndPermission();
|
||||
|
||||
_serviceCheckTimer = Timer.periodic(
|
||||
|
@ -124,6 +116,29 @@ class PermissionService extends StoppableService {
|
|||
_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() {
|
||||
if (_serviceCheckTimer != null) {
|
||||
_serviceCheckTimer!.cancel();
|
||||
|
|
|
@ -7,8 +7,6 @@ import '../models/session.dart';
|
|||
class StorageService {
|
||||
static const _sessionKey = 'session';
|
||||
static const _lastUrlKey = 'last_url';
|
||||
static const _storagePermissionDialogIgnoredKey =
|
||||
'storage_permission_ignored';
|
||||
|
||||
Future<bool> storeLastUrl(String url) {
|
||||
return _store(_lastUrlKey, url);
|
||||
|
@ -39,14 +37,6 @@ class StorageService {
|
|||
return _remove(_sessionKey);
|
||||
}
|
||||
|
||||
Future<bool> storeStoragePermissionDialogIgnored() {
|
||||
return _store(_storagePermissionDialogIgnoredKey, true.toString());
|
||||
}
|
||||
|
||||
Future<bool> hasStoragePermissionDialogIgnored() {
|
||||
return _exists(_storagePermissionDialogIgnoredKey);
|
||||
}
|
||||
|
||||
Future<bool> _exists(String key) async {
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
return prefs.containsKey(key);
|
||||
|
|
|
@ -108,7 +108,7 @@ class HistoryModel extends BaseModel {
|
|||
} else {
|
||||
errorMessage = translate('app.unknown_error');
|
||||
setStateView(ViewState.idle);
|
||||
_logger.e('An unknown error occurred', e);
|
||||
_logger.e('An unknown error occurred', error: e);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ class HistoryModel extends BaseModel {
|
|||
} else {
|
||||
errorMessage = translate('app.unknown_error');
|
||||
setStateView(ViewState.idle);
|
||||
_logger.e('An unknown error occurred', e);
|
||||
_logger.e('An unknown error occurred', error: e);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,7 +163,7 @@ class LoginModel extends BaseModel {
|
|||
errorMessage = translate('app.unknown_error');
|
||||
_sessionService.logout();
|
||||
setStateView(ViewState.idle);
|
||||
_logger.e('An unknown error occurred', e);
|
||||
_logger.e('An unknown error occurred', error: e);
|
||||
rethrow;
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ class ProfileModel extends BaseModel {
|
|||
setStateBoolValue(_configurationButtonLoading, false);
|
||||
_sessionService.logout();
|
||||
setStateBoolValue(_configurationButtonLoading, false);
|
||||
_logger.e('An unknown error occurred', e);
|
||||
_logger.e('An unknown error occurred', error: e);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:fbmobile/core/services/permission_service.dart';
|
||||
import 'package:flutter_translate/flutter_translate.dart';
|
||||
|
||||
import '../../locator.dart';
|
||||
|
@ -9,16 +10,18 @@ import 'base_model.dart';
|
|||
|
||||
class StartUpViewModel extends BaseModel {
|
||||
final SessionService _sessionService = locator<SessionService>();
|
||||
final PermissionService _permissionService = locator<PermissionService>();
|
||||
final NavigationService _navigationService = locator<NavigationService>();
|
||||
|
||||
Future handleStartUpLogic() async {
|
||||
setStateView(ViewState.busy);
|
||||
setStateMessage(translate('startup.init'));
|
||||
await Future.delayed(const Duration(milliseconds: 150));
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
|
||||
setStateMessage(translate('startup.start_services'));
|
||||
await _sessionService.start();
|
||||
await Future.delayed(const Duration(milliseconds: 150));
|
||||
await _permissionService.start();
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
|
||||
_navigationService.navigateAndReplaceTo(HomeView.routeName);
|
||||
|
||||
|
|
|
@ -152,9 +152,9 @@ class UploadModel extends BaseModel {
|
|||
))
|
||||
?.files;
|
||||
} on PlatformException catch (e) {
|
||||
_logger.e('Unsupported operation', e);
|
||||
_logger.e('Unsupported operation', error: e);
|
||||
} catch (ex) {
|
||||
_logger.e('An unknown error occurred', ex);
|
||||
_logger.e('An unknown error occurred', error: ex);
|
||||
}
|
||||
|
||||
loadingPath = false;
|
||||
|
@ -238,7 +238,7 @@ class UploadModel extends BaseModel {
|
|||
errorMessage = translate('app.unknown_error');
|
||||
setStateMessage(null);
|
||||
setStateView(ViewState.idle);
|
||||
_logger.e('An unknown error occurred', e);
|
||||
_logger.e('An unknown error occurred', error: e);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,9 @@ class HistoryView extends StatelessWidget {
|
|||
content: Text(translate('history.copy_link.copied')),
|
||||
duration: const Duration(seconds: 10),
|
||||
);
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
|
|
|
@ -53,24 +53,26 @@ class ProfileView extends StatelessWidget {
|
|||
UIHelper.verticalSpaceMedium(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 25.0, right: 25.0),
|
||||
child: model.configLoading
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const CircularProgressIndicator(),
|
||||
Text(translate('profile.show_config_loading')),
|
||||
],
|
||||
))
|
||||
: ElevatedButton.icon(
|
||||
icon: const Icon(Icons.settings, color: blueColor),
|
||||
label: Text(
|
||||
translate('profile.show_config'),
|
||||
),
|
||||
onPressed: () async {
|
||||
await model.showConfig(url);
|
||||
})),
|
||||
child: ElevatedButton.icon(
|
||||
icon: model.configLoading
|
||||
? Container(
|
||||
width: 24,
|
||||
height: 24,
|
||||
padding: const EdgeInsets.all(2.0),
|
||||
child: const CircularProgressIndicator(
|
||||
color: blueColor,
|
||||
strokeWidth: 3,
|
||||
),
|
||||
)
|
||||
: const Icon(Icons.settings, color: blueColor),
|
||||
label: Text(
|
||||
model.configLoading
|
||||
? translate('profile.show_config_loading')
|
||||
: translate('profile.show_config'),
|
||||
),
|
||||
onPressed: () async {
|
||||
await model.showConfig(url);
|
||||
})),
|
||||
UIHelper.verticalSpaceMedium(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 25.0, right: 25.0),
|
||||
|
|
|
@ -151,8 +151,10 @@ class UploadView extends StatelessWidget {
|
|||
duration:
|
||||
const Duration(seconds: 10),
|
||||
);
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(snackBar);
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(snackBar);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
|
@ -7,12 +7,11 @@ class MyAppBar extends AppBar {
|
|||
static final List<Widget> aboutDisabledWidgets = [];
|
||||
|
||||
MyAppBar(
|
||||
{Key? key,
|
||||
{super.key,
|
||||
required Widget title,
|
||||
List<Widget>? actionWidgets,
|
||||
bool enableAbout = true})
|
||||
: super(
|
||||
key: key,
|
||||
title: Row(children: <Widget>[title]),
|
||||
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,46 +11,47 @@ description: A mobile client for FileBin.
|
|||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
version: 1.6.1+19
|
||||
version: 1.6.4+22
|
||||
|
||||
environment:
|
||||
sdk: '>=2.19.4 <3.0.0'
|
||||
sdk: '>=3.5.0 <4.0.0'
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
cupertino_icons: 1.0.5
|
||||
cupertino_icons: 1.0.8
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
flutter_translate: 4.0.4
|
||||
provider: 6.0.5
|
||||
stacked: 3.3.0
|
||||
get_it: 7.6.0
|
||||
logger: 1.3.0
|
||||
shared_preferences: 2.1.1
|
||||
http: 0.13.6
|
||||
flutter_translate: 4.1.0
|
||||
provider: 6.1.2
|
||||
stacked: 3.4.3
|
||||
get_it: 7.7.0
|
||||
logger: 2.4.0
|
||||
shared_preferences: 2.3.2
|
||||
http: 1.2.2
|
||||
validators: 3.0.0
|
||||
flutter_linkify: 6.0.0
|
||||
url_launcher: 6.1.11
|
||||
url_launcher: 6.3.1
|
||||
expandable: 5.0.1
|
||||
share_plus: 7.0.1
|
||||
file_picker: 5.3.1
|
||||
share_plus: 10.1.1
|
||||
file_picker: 8.1.3
|
||||
clipboard: 0.1.3
|
||||
permission_handler: 10.2.0
|
||||
package_info_plus: 4.0.1
|
||||
json_annotation: ^4.8.1
|
||||
dynamic_color: 1.6.5
|
||||
intl: 0.18.0
|
||||
path: 1.8.3
|
||||
flutter_sharing_intent: 1.0.6
|
||||
permission_handler: 11.3.1
|
||||
package_info_plus: 8.1.0
|
||||
json_annotation: 4.9.0
|
||||
dynamic_color: 1.7.0
|
||||
intl: 0.19.0
|
||||
path: 1.9.0
|
||||
flutter_sharing_intent: 1.1.1
|
||||
device_info_plus: 11.1.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
build_runner: 2.4.4
|
||||
built_value_generator: 8.6.0
|
||||
json_serializable: 6.7.0
|
||||
flutter_lints: 2.0.1
|
||||
build_runner: 2.4.13
|
||||
built_value_generator: 8.9.2
|
||||
json_serializable: 6.8.0
|
||||
flutter_lints: 5.0.0
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://www.dartlang.org/tools/pub/pubspec
|
||||
|
|
38
renovate.json5
Normal file
38
renovate.json5
Normal file
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"$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