Compare commits

...

74 Commits

Author SHA1 Message Date
Vishnu Mohandas
bad2bafbe9 Merge pull request #53 from ente-io/search_ux
Improve UX for search
2023-02-06 15:48:13 +05:30
Neeraj Gupta
4f7b6e9f8e Merge pull request #52 from ente-io/low_end_key_derivation
Be verbose about the key derivation limits on low end devices
2023-02-06 15:39:20 +05:30
Neeraj Gupta
120fee358b bump version to 1.0.28+28 2023-02-06 15:38:18 +05:30
Neeraj Gupta
85cc5d7d18 bump version to 1.0.27+27 2023-02-06 15:37:53 +05:30
vishnukvmd
660b370d72 Be verbose about the key derivation limits on low end devices 2023-02-06 14:57:25 +05:30
Vishnu Mohandas
a23fd97f83 Merge pull request #51 from ente-io/handle_empty_account
Allow empty account name + bump version
2023-02-06 12:11:16 +05:30
Neeraj Gupta
1f83456b2b bump version to 1.0.27+27 2023-02-06 12:09:28 +05:30
Neeraj Gupta
28ea0d1b06 Allow adding code without account info 2023-02-06 12:08:55 +05:30
Neeraj Gupta
1584a23936 Merge pull request #49 from ente-io/handle_low_end_device
Fix: Attempt to avoid crash on low-spec devices
2023-02-06 11:39:37 +05:30
Neeraj Gupta
7fd0b8f407 Refactor and start with 256MB as memLimit for lowSpecDevices 2023-02-06 11:29:45 +05:30
Neeraj Gupta
bbe7525882 Switch to maxOpsLimit for low end devices 2023-02-06 10:21:49 +05:30
Neeraj Gupta
a9182577c0 Fix typo in comparision 2023-02-06 10:21:49 +05:30
Neeraj Gupta
7d6d3fe0f2 Switch to device_info_plus 2023-02-06 10:20:57 +05:30
Neeraj Gupta
303cdc92e7 Merge pull request #50 from ente-io/basic_search
Support for searching by account or issuer
2023-02-05 22:54:51 +05:30
Neeraj Gupta
3b39a34045 Support for searching by account or issuer 2023-02-05 22:33:37 +05:30
Vishnu Mohandas
2435c9ddef Merge pull request #48 from ente-io/fix_incorrect_scanning 2023-02-05 01:03:11 +05:30
Neeraj Gupta
35bb9284d6 Fix incorrect 2fa type detection 2023-02-05 01:02:16 +05:30
Neeraj Gupta
0c34cfcc5e Merge pull request #46 from ente-io/20_secret_with_spaces
Trim whitespaces from manual secret input
2023-01-28 18:44:56 +05:30
Neeraj Gupta
a0c2db5315 Merge pull request #45 from ente-io/34_url_decode
Fix: Url decode the path value
2023-01-28 18:44:46 +05:30
Neeraj Gupta
b8f1f00d2f Trim whitespaces from manual secret input 2023-01-28 18:42:32 +05:30
Neeraj Gupta
41c33003ac Fix: Url decode the path value 2023-01-28 18:27:59 +05:30
Neeraj Gupta
4103b776c4 Merge pull request #44 from ente-io/flutter_as_module
Add flutter as submodule
2023-01-28 15:46:06 +05:30
Manav
ae1986d7d3 Merge pull request #43 from ente-io/bump-build-number
1.0.25 (26)
2023-01-28 15:43:00 +05:30
Manav
3b6648074a 1.0.25 (26) 2023-01-28 15:42:03 +05:30
Neeraj Gupta
d5249d40cb Add flutter as submodule 2023-01-28 15:41:14 +05:30
Manav
a90f7e6abc Merge pull request #42 from ente-io/document-releases
Document automated releases
2023-01-28 15:37:37 +05:30
Manav
55722dd818 Merge pull request #41 from ente-io/playstore-submit
Upload to Google Play from GitHub action
2023-01-28 15:37:25 +05:30
Manav
7666c4e053 Document automated releases 2023-01-28 15:34:21 +05:30
Manav
cb93a0658f Use direct path
Removes the dependency of this build step on the previous build step.
2023-01-28 14:58:47 +05:30
Manav
97f665e8cf Remove unneeded mapping files 2023-01-28 14:57:55 +05:30
Manav
99516650fe Fix path 2023-01-28 14:01:10 +05:30
Manav
3928ccc6b7 Build a playstore variants 2023-01-28 13:49:42 +05:30
Manav
699f906843 Skeleton for upload-google-play 2023-01-28 13:39:24 +05:30
Manav
ca809a0e0b Merge pull request #40 from ente-io/apply-bis
Enable the BIS self classification flag
2023-01-28 13:02:18 +05:30
Manav
d52e0ed04a Enable the BIS self classification flag
We've submitted the BIS self classification report for the auth app alongwith
the photos app. More details: https://github.com/ente-io/photos-app/issues/427
2023-01-28 12:59:19 +05:30
Neeraj Gupta
c9936d68c1 Merge pull request #38 from ente-io/use_en_as_default
Restrict to en locale
2023-01-28 12:30:40 +05:30
Neeraj Gupta
59cfc88b4e Merge pull request #39 from ente-io/ua741-patch-1
Fix typo in read me
2023-01-28 12:14:15 +05:30
Neeraj Gupta
39f9385c74 Fix typo in read me 2023-01-28 12:13:16 +05:30
Neeraj Gupta
2017506b28 bump version to 1.0.25+25 2023-01-28 12:06:01 +05:30
Neeraj Gupta
1497866597 Restrict locale to en 2023-01-28 12:05:31 +05:30
Neeraj Gupta
78c12b5ee2 Merge pull request #35 from ente-io/24 2023-01-27 17:22:51 +05:30
Vishnu Mohandas
64159434d0 Merge pull request #36 from ente-io/xcloud 2023-01-26 16:39:23 +05:30
vishnukvmd
8bd1c1ec50 Update build script 2023-01-26 14:57:24 +05:30
vishnukvmd
409e9c39ca Update build file 2023-01-26 14:51:06 +05:30
vishnukvmd
73bd24da95 Add post clone CI script 2023-01-26 14:51:00 +05:30
vishnukvmd
aeb2f46a4f v1.0.24 2023-01-26 14:04:13 +05:30
vishnukvmd
cc9f8db288 Update build files 2023-01-26 14:04:06 +05:30
Vishnu Mohandas
83c70f0f6b Merge pull request #32 from ente-io/recents
Remove option to remove app from recents
2023-01-08 16:51:01 +05:30
Vishnu Mohandas
91fffc8b04 Merge pull request #31 from ente-io/tweak-trailing-margin-theme-picker
Increase trailing margin for the theme picker selection checkmark
2023-01-08 16:47:31 +05:30
Vishnu Mohandas
50b583c2d7 Merge pull request #30 from ente-io/use-newer-alternative
Use `AppLocalizations.localizationsDelegates` in other MaterialApp
2023-01-08 16:47:07 +05:30
vishnukvmd
0034da064f Remove option to remove app from recents 2023-01-08 16:38:04 +05:30
Manav
4fa61f0997 Use AppLocalizations.localizationsDelegates in other MaterialApp
Smoke tested by running the app on iOS simulator
2023-01-08 16:26:36 +05:30
Vishnu Mohandas
29bc7bb78f Merge pull request #29 from ente-io/fix-change-email-i18n-crash
Fix the crash on opening change email dialog
2023-01-08 16:16:55 +05:30
Manav
1df7d8de46 Fix the crash on opening change email dialog
The crash was happening in the `context.l10n` line in the
change_email_dialog.dart. This was because the root MaterialApp created by
AppLock wasn't being passed the AppLocalizations object.

Tested:
- Was able to reproduce the crash on iOS simulator (null check assertion)
- After the change, the crash doesn't happen
2023-01-08 16:05:40 +05:30
Manav
435fd6a1e7 Increase trailing margin for the theme picker selection checkmark 2023-01-08 15:26:05 +05:30
Vishnu Mohandas
c0f450d380 Merge pull request #27 from ente-io/reduce-cla-spam 2023-01-06 15:17:31 +05:30
Manav
9f686d38ed Run the CLA bot only on comments to PR
Right now, it unnecessarily runs and sends an email when customers open issues.

Not tested, but can test it by opening an issue after this is merged.

Reference:
- https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#issue_comment
2023-01-06 15:15:10 +05:30
Vishnu Mohandas
8ade294d7a Merge pull request #26 from ente-io/fix_typo
Fix copy
2022-12-31 11:30:57 +05:30
vishnukvmd
b5f3694805 Fix copy 2022-12-31 11:30:19 +05:30
Manav
1b1df0aa37 Merge pull request #25 from MalteKiefer/hotfix/german_language
fixed a forgotten string
2022-12-28 12:37:10 +05:30
Malte Kiefer
25dd92bdf0 fixed a forgotten string 2022-12-28 08:05:26 +01:00
Manav
e3ddc10a00 Merge pull request #24 from MalteKiefer/feature/language_german
translate app to german
2022-12-28 12:24:16 +05:30
Malte Kiefer
d0ae1ce566 translate app to german 2022-12-28 07:36:07 +01:00
Neeraj Gupta
b0eb0413f0 Separate icon config for fdroid 2022-12-18 08:59:05 +05:30
Neeraj Gupta
60a66efa79 Add fdroid flavor 2022-12-18 07:11:55 +05:30
Neeraj Gupta
e7c8437478 Merge branch 'main' of github.com:ente-io/auth 2022-12-18 06:43:35 +05:30
Neeraj Gupta
21ca31c1f3 Add fastlane details 2022-12-18 06:42:54 +05:30
Vishnu Mohandas
0330982eb0 Merge pull request #19 from ente-io/fix_window_manager_warning
Update warning dialog when "Hide from recents" is enabled
2022-12-15 22:36:19 +05:30
vishnukvmd
5fec321267 Update the warning copy since not all ROMs may block capturing of screenshots once FLAG_SECURE is set 2022-12-15 22:34:48 +05:30
Vishnu Mohandas
ca378d31d2 Merge pull request #17 from ente-io/ua741-patch-1 2022-12-15 14:08:33 +05:30
Neeraj Gupta
aedde8e447 Readme: Fix link to issues 2022-12-15 13:47:24 +05:30
Vishnu Mohandas
1f090ce3af Merge pull request #16 from ente-io/independent
Merge Independent APK track
2022-12-14 14:55:27 +05:30
vishnukvmd
308cf250fd v1.0.23 2022-12-14 14:43:20 +05:30
vishnukvmd
9ef9c3b9fd Migrate to open_filex 2022-12-14 14:43:05 +05:30
40 changed files with 669 additions and 363 deletions

View File

@@ -2,69 +2,85 @@ name: Flutter CI
# This workflow is triggered on pushes to the repository.
on:
workflow_dispatch:
# Enable manual run
push:
# Sequence of patterns matched against refs/tags
tags:
- 'v*' # Push events to matching v*, i.e. v4.2.0
workflow_dispatch:
# Enable manual run
push:
# Sequence of patterns matched against refs/tags
tags:
- "v*" # Push events to matching v*, i.e. v4.2.0
jobs:
build:
# This job will run on ubuntu virtual machine
runs-on: ubuntu-latest
steps:
build:
# This job will run on ubuntu virtual machine
runs-on: ubuntu-latest
steps:
# Setup Java environment in order to build the Android app.
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
distribution: "adopt"
java-version: "11"
# Setup Java environment in order to build the Android app.
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '11'
# Setup the flutter environment.
- uses: subosito/flutter-action@v2
with:
channel: "stable"
flutter-version: "3.3.8"
# Setup the flutter environment.
- uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: '3.3.8'
# Fetch sub modules
- run: git submodule update --init --recursive
# Fetch sub modules
- run: git submodule update --init --recursive
# Get flutter dependencies.
- run: flutter pub get
# Get flutter dependencies.
- run: flutter pub get
- name: Setup keys
uses: timheuer/base64-to-file@v1
with:
fileName: "keystore/ente_auth_key.jks"
encodedString: ${{ secrets.SIGNING_KEY }}
- name: Setup keys
uses: timheuer/base64-to-file@v1
with:
fileName: 'keystore/ente_auth_key.jks'
encodedString: ${{ secrets.SIGNING_KEY }}
# Build independent apk.
- name: Build
run: flutter build apk --release --flavor independent && mv build/app/outputs/flutter-apk/app-independent-release.apk build/app/outputs/flutter-apk/ente-auth.apk
env:
SIGNING_KEY_PATH: "/home/runner/work/_temp/keystore/ente_auth_key.jks"
SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }}
SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }}
SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }}
# Build independent apk.
- name: Build
run: flutter build apk --release --flavor independent && mv build/app/outputs/flutter-apk/app-independent-release.apk build/app/outputs/flutter-apk/ente-auth.apk
env:
SIGNING_KEY_PATH: '/home/runner/work/_temp/keystore/ente_auth_key.jks'
SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }}
SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }}
SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }}
# Build Play store aab.
- name: Build
run: flutter build appbundle --release --flavor playstore
env:
SIGNING_KEY_PATH: "/home/runner/work/_temp/keystore/ente_auth_key.jks"
SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }}
SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }}
SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }}
- name: Checksum
run: sha256sum build/app/outputs/flutter-apk/ente-auth.apk > build/app/outputs/flutter-apk/sha256sum
- name: Checksum
run: sha256sum build/app/outputs/flutter-apk/ente-auth.apk > build/app/outputs/flutter-apk/sha256sum
# Upload generated apk to the artifacts.
- uses: actions/upload-artifact@v2
with:
name: release-apk
path: build/app/outputs/flutter-apk/ente-auth.apk
# Upload generated apk to the artifacts.
- uses: actions/upload-artifact@v2
with:
name: release-apk
path: build/app/outputs/flutter-apk/ente-auth.apk
- uses: actions/upload-artifact@v2
with:
name: release-checksum
path: build/app/outputs/flutter-apk/sha256sum
- uses: actions/upload-artifact@v2
with:
name: release-checksum
path: build/app/outputs/flutter-apk/sha256sum
# Create a Github release
- uses: ncipollo/release-action@v1
with:
artifacts: "build/app/outputs/flutter-apk/ente-auth.apk,build/app/outputs/flutter-apk/sha256sum"
token: ${{ secrets.GITHUB_TOKEN }}
# Create a Github release
- uses: ncipollo/release-action@v1
with:
artifacts: "build/app/outputs/flutter-apk/ente-auth.apk,build/app/outputs/flutter-apk/sha256sum"
token: ${{ secrets.GITHUB_TOKEN }}
# Upload to Play store
- uses: ente-io/upload-google-play@v1
with:
serviceAccountJsonPlainText: ${{ secrets.SERVICE_ACCOUNT_JSON }}
packageName: io.ente.auth
releaseFiles: build/app/outputs/bundle/playstoreRelease/app-playstore-release.aab
track: internal

View File

@@ -7,6 +7,8 @@ on:
jobs:
CLAAssistant:
# This job only runs for pull request comments
if: ${{ github.event.issue.pull_request }}
runs-on: ubuntu-latest
steps:
- name: "CLA Assistant"

4
.gitmodules vendored
View File

@@ -2,3 +2,7 @@
path = thirdparty/sentry-dart
url = https://github.com/ente-io/sentry-dart.git
branch = sentry_flutter_ente
[submodule "flutter"]
path = flutter
url = https://github.com/flutter/flutter.git
branch = stable

View File

@@ -48,7 +48,7 @@ file, that adheres to the above format.
### Android
This repository's [GitHub
releases](https://github.com/ente-io/auth/releases/latest/download/ente-auth.apks)
releases](https://github.com/ente-io/auth/releases/latest/download/ente-auth.apk)
contains APKs, built straight from source. These builds keep themselves updated,
without relying on third party stores.
@@ -88,13 +88,16 @@ tokens has been documented [here](architecture/README.md).
4. For Android, run `flutter build apk --release --flavor independent`
5. For iOS, run `flutter build ios`
For maintainers, there is [additional documentation](RELEASES.md) on
automatically publishing the main branch to App store, Play store and GitHub
releases.
## 🙋‍♂️ Support
If you need help, please reach out to support@ente.io, and a human will get in
touch with you.
If you have feature requests, please create a [GitHub issue](./issues).
If you have feature requests, please create a [GitHub issue](https://github.com/ente-io/auth/issues/).
If you wish to support us, please ⭐
[star](https://github.com/ente-io/auth/stargazers) this project.

12
RELEASES.md Normal file
View File

@@ -0,0 +1,12 @@
# Releases
1. Create a PR to bump up the version number in `pubspec.yaml`.
2. Once that is merged, tag main. This'll trigger the
[workflow](.github/workflows/ci.yml) to (a) create a new GitHub release with
the independently distributed APK, and (b) build and upload a release to
Google Play.
3. Xcode Cloud has already been configured and will automatically build and
release to TestFlight when step 1 was merged to main (you can see logs under
the PR checks).

View File

@@ -72,6 +72,9 @@ android {
playstore {
dimension "default"
}
fdroid {
dimension "default"
}
}
buildTypes {

View File

@@ -0,0 +1 @@
- Hello, FDroid!

View File

@@ -0,0 +1,35 @@
ente authenticator provides end-to-end encrypted cloud backups so that you don't have to worry about losing your tokens. We use the same protocols [ente
Photos](https://ente.io) uses to encrypt and preserve your data.
Multi Device Synchronization
ente will automatically sync the 2FA tokens you add to your account, across all
your devices. Every new device you sign into will have access to these tokens.
Mode
ente generates 2FA tokens offline, so your network connectivity will not get in
the way of your workflow.
Import and Export Tokens
You can add tokens to ente by one of the following methods:
1. Scanning a QR code
2. Manually entering (copy-pasting) a 2FA secret
3. Bulk importing from a file that contains a list of codes in the following
format:
```
otpauth://totp/ACCOUNT?secret=SUPERSECRET&issuer=SERVICE
```
The codes maybe separated by new lines or commas.
You can also export the codes you have added to ente, to an **unencrypted** text
file, that adheres to the above format.
SUPPORT
We take pride in offering human support. If you are our paid customer, you can reach out to team@ente.io and expect a response from our team within 24 hours.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

@@ -0,0 +1 @@
ente is an end-to-end encrypted authenticator app

View File

@@ -0,0 +1 @@
ente Authenticator

View File

@@ -0,0 +1,6 @@
flutter_icons:
android: "launcher_icon"
image_path: "assets/icon-light.png"
adaptive_icon_foreground: "assets/icon-light-adaptive-fg.png"
adaptive_icon_background: "#ffffff"

1
flutter Submodule

Submodule flutter added at b06b8b2710

View File

@@ -2,7 +2,7 @@ PODS:
- connectivity (0.0.1):
- Flutter
- Reachability
- device_info (0.0.1):
- device_info_plus (0.0.1):
- Flutter
- DKImagePickerController/Core (4.3.4):
- DKImagePickerController/ImageDataManager
@@ -54,7 +54,7 @@ PODS:
- Flutter
- flutter_native_splash (0.0.1):
- Flutter
- flutter_secure_storage (3.3.1):
- flutter_secure_storage (6.0.0):
- Flutter
- flutter_sodium (0.0.1):
- Flutter
@@ -69,38 +69,42 @@ PODS:
- move_to_background (0.0.1):
- Flutter
- MTBBarcodeScanner (5.0.11)
- open_filex (0.0.2):
- Flutter
- OrderedSet (5.0.0)
- package_info_plus (0.4.5):
- Flutter
- path_provider_ios (0.0.1):
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- qr_code_scanner (0.2.0):
- Flutter
- MTBBarcodeScanner
- Reachability (3.2)
- SDWebImage (5.13.4):
- SDWebImage/Core (= 5.13.4)
- SDWebImage/Core (5.13.4)
- Sentry/HybridSDK (7.30.2)
- SDWebImage (5.15.0):
- SDWebImage/Core (= 5.15.0)
- SDWebImage/Core (5.15.0)
- Sentry/HybridSDK (7.31.5)
- sentry_flutter (0.0.1):
- Flutter
- FlutterMacOS
- Sentry/HybridSDK (= 7.30.2)
- Sentry/HybridSDK (= 7.31.5)
- share_plus (0.0.1):
- Flutter
- shared_preferences_ios (0.0.1):
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- sqflite (0.0.2):
- Flutter
- FMDB (>= 2.7.5)
- SwiftyGif (5.4.3)
- SwiftyGif (5.4.4)
- Toast (4.0.0)
- url_launcher_ios (0.0.1):
- Flutter
DEPENDENCIES:
- connectivity (from `.symlinks/plugins/connectivity/ios`)
- device_info (from `.symlinks/plugins/device_info/ios`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- file_picker (from `.symlinks/plugins/file_picker/ios`)
- fk_user_agent (from `.symlinks/plugins/fk_user_agent/ios`)
- Flutter (from `Flutter`)
@@ -113,12 +117,13 @@ DEPENDENCIES:
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
- local_auth (from `.symlinks/plugins/local_auth/ios`)
- move_to_background (from `.symlinks/plugins/move_to_background/ios`)
- open_filex (from `.symlinks/plugins/open_filex/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`)
- qr_code_scanner (from `.symlinks/plugins/qr_code_scanner/ios`)
- sentry_flutter (from `.symlinks/plugins/sentry_flutter/ios`)
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
@@ -138,8 +143,8 @@ SPEC REPOS:
EXTERNAL SOURCES:
connectivity:
:path: ".symlinks/plugins/connectivity/ios"
device_info:
:path: ".symlinks/plugins/device_info/ios"
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
file_picker:
:path: ".symlinks/plugins/file_picker/ios"
fk_user_agent:
@@ -164,18 +169,20 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/local_auth/ios"
move_to_background:
:path: ".symlinks/plugins/move_to_background/ios"
open_filex:
:path: ".symlinks/plugins/open_filex/ios"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_ios:
:path: ".symlinks/plugins/path_provider_ios/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/ios"
qr_code_scanner:
:path: ".symlinks/plugins/qr_code_scanner/ios"
sentry_flutter:
:path: ".symlinks/plugins/sentry_flutter/ios"
share_plus:
:path: ".symlinks/plugins/share_plus/ios"
shared_preferences_ios:
:path: ".symlinks/plugins/shared_preferences_ios/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/ios"
sqflite:
:path: ".symlinks/plugins/sqflite/ios"
url_launcher_ios:
@@ -183,37 +190,38 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
connectivity: c4130b2985d4ef6fd26f9702e886bd5260681467
device_info: d7d233b645a32c40dfdc212de5cf646ca482f175
device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed
DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
file_picker: 817ab1d8cd2da9d2da412a417162deee3500fc95
file_picker: ce3938a0df3cc1ef404671531facef740d03f920
fk_user_agent: 1f47ec39291e8372b1d692b50084b0d54103c545
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_email_sender: 02d7443217d8c41483223627972bfdc09f74276b
flutter_inappwebview: bfd58618f49dc62f2676de690fc6dcda1d6c3721
flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
flutter_sodium: c84426b4de738514b5b66cfdeb8a06634e72fe0b
fluttertoast: 74526702fea2c060ea55dde75895b7e1bde1c86b
fluttertoast: eb263d302cc92e04176c053d2385237e9f43fad0
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
local_auth: 1740f55d7af0a2e2a8684ce225fe79d8931e808c
move_to_background: 39a5b79b26d577b0372cbe8a8c55e7aa9fcd3a2d
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
open_filex: 6e26e659846ec990262224a12ef1c528bb4edbe4
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
path_provider_foundation: 37748e03f12783f9de2cb2c4eadfaa25fe6d4852
qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
SDWebImage: e5cc87bf736e60f49592f307bdf9e157189298a3
Sentry: 9be48e341494bc976c963b05aa4a8ca48308c684
sentry_flutter: 544e6376e35b00eef9f0864f8bb7f10a0e204993
SDWebImage: 9bec4c5cdd9579e1f57104735ee0c37df274d593
Sentry: 4c9babff9034785067c896fd580b1f7de44da020
sentry_flutter: b10ae7a5ddcbc7f04648eeb2672b5747230172f1
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
shared_preferences_foundation: 297b3ebca31b34ec92be11acd7fb0ba932c822ca
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
SwiftyGif: 6c3eafd0ce693cad58bb63d2b2fb9bacb8552780
SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
url_launcher_ios: ae1517e5e344f5544fb090b079e11f399dfbe4d2
PODFILE CHECKSUM: b4e3a7eabb03395b66e81fc061789f61526ee6bb

View File

@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 51;
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@@ -220,6 +220,7 @@
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@@ -256,7 +257,7 @@
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
buildActionMask = 8;
files = (
);
inputPaths = (
@@ -264,9 +265,9 @@
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
runOnlyForDeploymentPostprocessing = 1;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
};
/* End PBXShellScriptBuildPhase section */

View File

@@ -31,6 +31,8 @@
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>MinimumOSVersion</key>
<string>12.0</string>
<key>NSCameraUsageDescription</key>

24
ios/ci_scripts/ci_post_clone.sh Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/sh
# by default, the execution directory of this script is the ci_scripts directory
# CI_WORKSPACE is the directory of your cloned repo
echo "🟩 Navigate from ($PWD) to ($CI_WORKSPACE)"
cd $CI_WORKSPACE
echo "🟩 Install Flutter"
time git clone https://github.com/flutter/flutter.git -b stable $HOME/flutter
export PATH="$PATH:$HOME/flutter/bin"
echo "🟩 Flutter Precache"
time flutter precache --ios
echo "🟩 Install Flutter Dependencies"
time flutter pub get
echo "🟩 Install CocoaPods via Homebrew"
time HOMEBREW_NO_AUTO_UPDATE=1 brew install cocoapods
echo "🟩 Install CocoaPods dependencies..."
time cd ios && pod install
exit 0

View File

@@ -27,6 +27,9 @@ class App extends StatefulWidget {
class _AppState extends State<App> {
StreamSubscription<SignedOutEvent> _signedOutEvent;
StreamSubscription<SignedInEvent> _signedInEvent;
static const List<Locale> supportedLocales = <Locale>[
Locale('en'),
];
@override
void initState() {
@@ -78,13 +81,17 @@ class _AppState extends State<App> {
theme: lightTheme,
darkTheme: dartTheme,
debugShowCheckedModeBanner: false,
supportedLocales: AppLocalizations.supportedLocales,
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: supportedLocales,
localeListResolutionCallback: (locales, supportedLocales) {
for (Locale locale in locales) {
if (supportedLocales.contains(locale)) {
return locale;
}
}
// if device language is not supported by the app, use en as default
return const Locale('en');
},
localizationsDelegates: AppLocalizations.localizationsDelegates,
routes: _getRoutes,
),
);
@@ -95,7 +102,16 @@ class _AppState extends State<App> {
theme: lightThemeData,
darkTheme: darkThemeData,
debugShowCheckedModeBanner: false,
supportedLocales: AppLocalizations.supportedLocales,
supportedLocales: supportedLocales,
localeListResolutionCallback: (locales, supportedLocales) {
for (Locale locale in locales) {
if (supportedLocales.contains(locale)) {
return locale;
}
}
// if device language is not supported by the app, use en as default
return const Locale('en');
},
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,

View File

@@ -31,7 +31,6 @@ class Configuration {
static const emailKey = "email";
static const keyAttributesKey = "key_attributes";
static const keyKey = "key";
static const keyShouldHideFromRecents = "should_hide_from_recents";
static const keyShouldShowLockScreen = "should_show_lock_screen";
static const lastTempFolderClearTimeKey = "last_temp_folder_clear_time";
static const secretKeyKey = "secret_key";
@@ -453,14 +452,6 @@ class Configuration {
return _preferences.setBool(keyShouldShowLockScreen, value);
}
bool shouldHideFromRecents() {
return _preferences.getBool(keyShouldHideFromRecents) ?? false;
}
Future<void> setShouldHideFromRecents(bool value) {
return _preferences.setBool(keyShouldHideFromRecents, value);
}
void setVolatilePassword(String volatilePassword) {
_volatilePassword = volatilePassword;
}

116
lib/l10n/arb/app_de.arb Normal file
View File

@@ -0,0 +1,116 @@
{
"@@locale": "de",
"counterAppBarTitle": "Zähler",
"@counterAppBarTitle": {
"description": "Text, der in der AppBar der Zähler-Seite angezeigt wird"
},
"onBoardingBody": "Sichern Sie Ihre 2FA-Codes",
"onBoardingGetStarted": "Los geht's",
"setupFirstAccount": "Ihr erstes Konto einrichten",
"importScanQrCode": "Scannen eines QR-Codes",
"importEnterSetupKey": "Einen Setup-Schlüssel eingeben",
"importAccountPageTitle": "Kontodaten eingeben",
"codeIssuerHint": "Aussteller",
"codeSecretKeyHint" : "Geheimer Schlüssel",
"codeAccountHint": "Konto (you@domain.com)",
"accountKeyType": "Art des Schlüssels",
"timeBasedKeyType": "Zeitbasiert (TOTP)",
"counterBasedKeyType": "Zählerbasiert (HOTP)",
"saveAction": "Speichern",
"nextTotpTitle": "Weiter",
"deleteCodeTitle": "Code löschen?",
"deleteCodeMessage": "Sind Sie sicher, dass Sie diesen Code löschen wollen? Diese Aktion ist unumkehrbar.",
"viewLogsAction": "Protokolle anzeigen",
"sendLogsDescription": "Dadurch werden Protokolle übermittelt, die uns bei der Behebung Ihres Problems helfen. Obwohl wir Vorkehrungen treffen, um sicherzustellen, dass keine sensiblen Informationen protokolliert werden, empfehlen wir Ihnen, diese Protokolle anzusehen, bevor Sie sie weitergeben.",
"preparingLogsTitle": "Vorbereiten der Protokolle...",
"emailLogsTitle": "Protokolle versenden",
"emailLogsMessage": "Bitte senden Sie die Protokolle an {email}",
"@emailLogsMessage": {
"placeholders": {
"email": {
"type": "String"
}
}
},
"copyEmailAction": "E-Mail kopieren",
"exportLogsAction": "Protokolle exportieren",
"reportABug": "Fehlermelden",
"crashAndErrorReporting": "Absturz- und Fehlerberichte",
"reportBug": "Fehlermelden",
"emailUsMessage": "Bitte senden Sie uns eine E-Mail an {email}",
"@emailUsMessage": {
"placeholders": {
"email": {
"type": "String"
}
}
},
"contactSupport": "Support kontaktieren",
"verifyPassword": "Passwort überprüfen",
"pleaseWaitTitle": "Bitte warten...",
"generatingEncryptionKeysTitle": "Generierung von Verschlüsselungsschlüsseln...",
"recreatePassword": "Passwort wiederherstellen",
"recreatePasswordMessage": "Das aktuelle Gerät ist nicht leistungsfähig genug, um Ihr Passwort zu verifizieren, daher müssen wir es einmalig auf eine Weise neu generieren, die mit allen Geräten funktioniert. \n\nBitte melden Sie sich mit Ihrem Wiederherstellungsschlüssel an und generieren Sie Ihr Passwort neu (Sie können dasselbe erneut verwenden, wenn Sie möchten).",
"useRecoveryKeyAction": "Wiederherstellungsschlüssel verwenden",
"incorrectPassword": "Falsches Passwort",
"welcomeBackTitle": "Willkommen zurück!",
"madeWithLoveAtPrefix": "gemacht mit ❤️ bei ",
"changeEmail": "E-Mail ändern",
"ok": "OK",
"cancel": "Abbrechen",
"yes": "Ja",
"no": "Nein",
"email": "E-Mail",
"support": "Support",
"settings": "Einstellungen",
"copied": "Kopiert",
"tryAgainMessage": "Bitte versuchen Sie es erneut",
"existingUser": "Bestehender Benutzer",
"newUser" : "Neu bei ente",
"delete": "Löschen",
"enterYourPasswordHint": "Geben Sie Ihr Passwort ein",
"forgotPassword": "Passwort vergessen",
"oops": "Oops",
"somethingWentWrongMessage": "Ein Fehler ist aufgetreten, bitte versuchen Sie es erneut",
"leaveFamily": "Familie verlassen",
"leaveFamilyMessage": "Sind Sie sicher, dass Sie den Familien-Plan verlassen wollen?",
"inFamilyPlanMessage": "Sie haben einen Familien-Plan!",
"swipeHint": "Wischen Sie nach links, um Codes zu bearbeiten oder zu entfernen",
"scan": "Scannen",
"scanACode": "Scannen eines Codes",
"verify": "Überprüfen Sie",
"enterCodeHint": "Geben Sie den 6-stelligen Code \naus Ihrer Authentifikator-App ein.",
"lostDeviceTitle": "Gerät verloren?",
"twoFactorAuthTitle": "Zwei-Faktor-Authentifizierung",
"recoverAccount": "Konto wiederherstellen",
"enterRecoveryKeyHint": "Geben Sie Ihren Wiederherstellungsschlüssel ein",
"recover": "Wiederherstellen",
"contactSupportViaEmailMessage":"Bitte senden Sie eine E-Mail an {email} von Ihrer registrierten E-Mail-Adresse",
"@contactSupportViaEmailMessage": {
"placeholders": {
"email": {
"type": "String"
}
}
},
"noRecoveryKeyTitle": "Kein Wiederherstellungsschlüssel?",
"enterEmailHint": "Geben Sie Ihre E-Mail Adresse ein",
"invalidEmailTitle": "Ungültige E-Mail Adresse",
"invalidEmailMessage": "Bitte geben Sie eine gültige E-Mail Adresse ein.",
"deleteAccount": "Konto löschen",
"deleteAccountQuery": "Es wird uns leid tun, Sie gehen zu sehen. Haben Sie ein Problem?",
"yesSendFeedbackAction": "Ja, Feedback senden",
"noDeleteAccountAction": "Nein, Konto löschen",
"initiateAccountDeleteTitle": "Bitte authentifizieren Sie sich, um die Kontolöschung einzuleiten",
"confirmAccountDeleteTitle": "Sind Sie sicher, dass Sie Ihr ente Konto löschen wollen?",
"confirmAccountDeleteMessage": "Ihre hochgeladenen Daten werden in allen Anwendungen (sowohl Fotos als auch Authenticator) zur Löschung vorgesehen und Ihr Konto wird dauerhaft gelöscht.",
"sendEmail": "E-Mail senden",
"createNewAccount": "Neues Konto erstellen",
"passwordStrengthWeak": "Schwach",
"passwordStrengthStrong": "Stark",
"passwordStrengthModerate": "Mittel",
"confirmPassword": "Bestätigen Sie das Passwort",
"close": "Schließen",
"oopsSomethingWentWrong": "Ups, da ist etwas schief gelaufen."
}

View File

@@ -67,7 +67,8 @@ class Code {
static String _getAccount(Uri uri) {
try {
return uri.path.split(':')[1];
final String path = Uri.decodeComponent(uri.path);
return path.split(':')[1];
} catch (e) {
return "";
}
@@ -75,7 +76,8 @@ class Code {
static String _getIssuer(Uri uri) {
try {
return uri.path.split(':')[0].substring(1);
final String path = Uri.decodeComponent(uri.path);
return path.split(':')[0].substring(1);
} catch (e) {
return "";
}
@@ -113,7 +115,12 @@ class Code {
}
static Type _getType(Uri uri) {
return uri.host == "totp" ? Type.totp : Type.hotp;
if (uri.host == "totp") {
return Type.totp;
} else if (uri.host == "hotp") {
return Type.hotp;
}
throw UnsupportedError("Unsupported format with host ${uri.host}");
}
@override

View File

@@ -104,16 +104,23 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
width: 400,
child: OutlinedButton(
onPressed: () {
if (_accountController.text.trim().isEmpty ||
if ((_accountController.text.trim().isEmpty &&
_issuerController.text.trim().isEmpty) ||
_secretController.text.trim().isEmpty) {
_showIncorrectDetailsDialog(context);
String message;
if (_secretController.text.trim().isEmpty) {
message = "Secret can not be empty";
} else {
message = "Both account and issuer can not be empty";
}
_showIncorrectDetailsDialog(context, message: message);
return;
}
try {
final code = Code.fromAccountAndSecret(
_accountController.text.trim(),
_issuerController.text.trim(),
_secretController.text.trim(),
_secretController.text.trim().replaceAll(' ', ''),
);
// Verify the validity of the code
getTotp(code);
@@ -142,11 +149,14 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
);
}
void _showIncorrectDetailsDialog(BuildContext context) {
void _showIncorrectDetailsDialog(
BuildContext context, {
String message = "Please verify the entered details",
}) {
showErrorDialog(
context,
"Incorrect details",
"Please verify the entered details",
message,
);
}
}

View File

@@ -12,6 +12,9 @@ class MenuItemWidget extends StatefulWidget {
final IconData? trailingIcon;
final Widget? trailingSwitch;
final bool trailingIconIsMuted;
/// If provided, add this much extra spacing to the right of the trailing icon.
final double trailingExtraMargin;
final VoidCallback? onTap;
final VoidCallback? onDoubleTap;
final Color? menuItemColor;
@@ -27,6 +30,7 @@ class MenuItemWidget extends StatefulWidget {
this.trailingIcon,
this.trailingSwitch,
this.trailingIconIsMuted = false,
this.trailingExtraMargin = 0.0,
this.onTap,
this.onDoubleTap,
this.menuItemColor,
@@ -141,11 +145,15 @@ class _MenuItemWidgetState extends State<MenuItemWidget> {
),
)
: widget.trailingIcon != null
? Icon(
widget.trailingIcon,
color: widget.trailingIconIsMuted
? enteColorScheme.strokeMuted
: null,
? Padding(
padding:
EdgeInsets.only(right: widget.trailingExtraMargin),
child: Icon(
widget.trailingIcon,
color: widget.trailingIconIsMuted
? enteColorScheme.strokeMuted
: null,
),
)
: widget.trailingSwitch ?? const SizedBox.shrink(),
],

View File

@@ -34,29 +34,55 @@ class _HomePageState extends State<HomePage> {
);
bool _hasLoaded = false;
bool _isSettingsOpen = false;
final TextEditingController _textController = TextEditingController();
bool _showSearchBox = false;
String _searchText = "";
List<Code> _codes = [];
List<Code> _filteredCodes = [];
StreamSubscription<CodesUpdatedEvent>? _streamSubscription;
@override
void initState() {
super.initState();
_textController.addListener(_applyFiltering);
_loadCodes();
_streamSubscription = Bus.instance.on<CodesUpdatedEvent>().listen((event) {
_loadCodes();
});
super.initState();
}
void _loadCodes() {
CodeStore.instance.getAllCodes().then((codes) {
_codes = codes;
_filteredCodes = codes;
_hasLoaded = true;
setState(() {});
});
}
void _applyFiltering() {
if (_searchText.isNotEmpty && _showSearchBox) {
final String val = _searchText.toLowerCase();
_filteredCodes = _codes
.where(
(element) => (element.account.toLowerCase().contains(val) ||
element.issuer.toLowerCase().contains(val)),
)
.toList();
} else {
_filteredCodes = _codes;
}
if (mounted) {
setState(() {});
}
}
@override
void dispose() {
_streamSubscription?.cancel();
_textController.removeListener(_applyFiltering);
super.dispose();
}
@@ -121,7 +147,41 @@ class _HomePageState extends State<HomePage> {
),
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: const Text('ente Authenticator'),
title: !_showSearchBox
? const Text('ente Authenticator')
: TextField(
autofocus: _searchText.isEmpty,
controller: _textController,
onChanged: (val) {
_searchText = val;
_applyFiltering();
},
decoration: const InputDecoration(
hintText: 'Search...',
border: InputBorder.none,
),
),
actions: <Widget>[
IconButton(
icon: _showSearchBox
? const Icon(Icons.clear)
: const Icon(Icons.search),
tooltip: 'Search',
onPressed: () {
setState(
() {
_showSearchBox = !_showSearchBox;
if (!_showSearchBox) {
_textController.clear();
} else {
_searchText = _textController.text;
}
_applyFiltering();
},
);
},
),
],
),
floatingActionButton: !_hasLoaded ||
_codes.isEmpty ||
@@ -134,14 +194,14 @@ class _HomePageState extends State<HomePage> {
Widget _getBody() {
if (_hasLoaded) {
if (_codes.isEmpty) {
if (_filteredCodes.isEmpty && _searchText.isEmpty) {
return _getEmptyState();
} else {
final list = ListView.builder(
itemBuilder: ((context, index) {
return CodeWidget(_codes[index]);
return CodeWidget(_filteredCodes[index]);
}),
itemCount: _codes.length,
itemCount: _filteredCodes.length,
);
if (!PreferenceService.instance.hasShownCoachMark()) {
return Stack(
@@ -150,6 +210,21 @@ class _HomePageState extends State<HomePage> {
_getCoachMarkWidget(),
],
);
} else if (_showSearchBox) {
return Column(
children: [
Expanded(
child: _filteredCodes.isNotEmpty
? ListView.builder(
itemBuilder: ((context, index) {
return CodeWidget(_filteredCodes[index]);
}),
itemCount: _filteredCodes.length,
)
: const Center(child: (Text("No result"))),
),
],
);
} else {
return list;
}

View File

@@ -6,7 +6,7 @@ import 'package:ente_auth/ente_theme_data.dart';
import 'package:ente_auth/services/update_service.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:open_file/open_file.dart';
import 'package:open_filex/open_filex.dart';
class AppUpdateDialog extends StatefulWidget {
final LatestVersionInfo latestVersionInfo;
@@ -157,7 +157,7 @@ class _ApkDownloaderDialogState extends State<ApkDownloaderDialog> {
},
);
Navigator.of(context, rootNavigator: true).pop('dialog');
OpenFile.open(_saveUrl);
OpenFilex.open(_saveUrl);
} catch (e) {
Logger("ApkDownloader").severe(e);
final AlertDialog alert = AlertDialog(

View File

@@ -1,9 +1,6 @@
// @dart=2.9
import 'dart:io';
import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/ente_theme_data.dart';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/services/local_authentication_service.dart';
import 'package:ente_auth/theme/ente_theme.dart';
@@ -14,7 +11,6 @@ import 'package:ente_auth/ui/components/menu_item_widget.dart';
import 'package:ente_auth/ui/components/toggle_switch_widget.dart';
import 'package:ente_auth/ui/settings/common_settings.dart';
import 'package:flutter/material.dart';
import 'package:flutter_windowmanager/flutter_windowmanager.dart';
class SecuritySectionWidget extends StatefulWidget {
const SecuritySectionWidget({Key key}) : super(key: key);
@@ -70,97 +66,6 @@ class _SecuritySectionWidgetState extends State<SecuritySectionWidget> {
),
),
sectionOptionSpacing,
]);
if (Platform.isAndroid) {
children.addAll(
[
MenuItemWidget(
captionedTextWidget: const CaptionedTextWidget(
title: "Hide from recents",
),
trailingSwitch: ToggleSwitchWidget(
value: _config.shouldHideFromRecents(),
onChanged: (value) async {
if (value) {
final AlertDialog alert = AlertDialog(
title: const Text("Hide from recents?"),
content: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(
"Hiding from the task switcher will prevent you from taking screenshots in this app.",
style: TextStyle(
height: 1.5,
),
),
Padding(padding: EdgeInsets.all(8)),
Text(
"Are you sure?",
style: TextStyle(
height: 1.5,
),
),
],
),
),
actions: [
TextButton(
child: Text(
l10n.no,
style: TextStyle(
color:
Theme.of(context).colorScheme.defaultTextColor,
),
),
onPressed: () {
Navigator.of(context, rootNavigator: true)
.pop('dialog');
},
),
TextButton(
child: Text(
l10n.yes,
style: TextStyle(
color:
Theme.of(context).colorScheme.defaultTextColor,
),
),
onPressed: () async {
Navigator.of(context, rootNavigator: true)
.pop('dialog');
await _config.setShouldHideFromRecents(true);
await FlutterWindowManager.addFlags(
FlutterWindowManager.FLAG_SECURE,
);
setState(() {});
},
),
],
);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
} else {
await _config.setShouldHideFromRecents(false);
await FlutterWindowManager.clearFlags(
FlutterWindowManager.FLAG_SECURE,
);
setState(() {});
}
},
),
),
sectionOptionSpacing,
],
);
}
children.addAll([
MenuItemWidget(
captionedTextWidget: const CaptionedTextWidget(
title: "Active sessions",

View File

@@ -73,6 +73,7 @@ class _ThemeSwitchWidgetState extends State<ThemeSwitchWidget> {
pressedColor: getEnteColorScheme(context).fillFaint,
isExpandable: false,
trailingIcon: currentThemeMode == themeMode ? Icons.check : null,
trailingExtraMargin: 4,
onTap: () async {
AdaptiveTheme.of(context).setThemeMode(themeMode);
currentThemeMode = themeMode;

View File

@@ -3,6 +3,7 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
/// A widget which handles app lifecycle events for showing and hiding a lock screen.
/// This should wrap around a `MyApp` widget (or equivalent).
@@ -107,6 +108,8 @@ class _AppLockState extends State<AppLock> with WidgetsBindingObserver {
themeMode: ThemeMode.system,
theme: widget.lightTheme,
darkTheme: widget.darkTheme,
supportedLocales: AppLocalizations.supportedLocales,
localizationsDelegates: AppLocalizations.localizationsDelegates,
onGenerateRoute: (settings) {
switch (settings.name) {
case '/lock-screen':

View File

@@ -59,7 +59,7 @@ class _LockScreenState extends State<LockScreen> {
_logger.info("Showing lockscreen");
try {
final result = await requestAuthentication(
"Please authenticate to view your memories",
"Please authenticate to view your secrets",
);
if (result) {
AppLock.of(context).didUnlock();

View File

@@ -4,6 +4,7 @@ import 'dart:typed_data';
import 'package:computer/computer.dart';
import 'package:ente_auth/models/derived_key_result.dart';
import 'package:ente_auth/models/encryption_result.dart';
import 'package:ente_auth/utils/device_info.dart';
import 'package:flutter_sodium/flutter_sodium.dart';
import 'package:logging/logging.dart';
@@ -287,16 +288,38 @@ class CryptoUtil {
Uint8List salt,
) async {
final logger = Logger("pwhash");
// Default with 1 GB mem and 4 ops limit
int memLimit = Sodium.cryptoPwhashMemlimitSensitive;
int opsLimit = Sodium.cryptoPwhashOpslimitSensitive;
if (await isLowSpecDevice()) {
logger.info("low spec device detected");
// When sensitive memLimit (1 GB) is used, on low spec device the OS might
// kill the app with OOM. To avoid that, start with 256 MB and
// corresponding ops limit (16).
// This ensures that the product of these two variables
// (the area under the graph that determines the amount of work required)
// stays the same
// SODIUM_CRYPTO_PWHASH_MEMLIMIT_SENSITIVE: 1073741824
// SODIUM_CRYPTO_PWHASH_MEMLIMIT_MODERATE: 268435456
// SODIUM_CRYPTO_PWHASH_OPSLIMIT_SENSITIVE: 4
memLimit = Sodium.cryptoPwhashMemlimitModerate;
final factor = Sodium.cryptoPwhashMemlimitSensitive ~/
Sodium.cryptoPwhashMemlimitModerate; // = 4
opsLimit = opsLimit * factor; // = 16
}
Uint8List key;
while (memLimit > Sodium.cryptoPwhashMemlimitMin &&
opsLimit < Sodium.cryptoPwhashOpslimitMax) {
while (memLimit >= Sodium.cryptoPwhashMemlimitMin &&
opsLimit <= Sodium.cryptoPwhashOpslimitMax) {
try {
key = await deriveKey(password, salt, memLimit, opsLimit);
return DerivedKeyResult(key, memLimit, opsLimit);
} catch (e, s) {
logger.severe(e, s);
logger.severe(
"failed to derive memLimit: $memLimit and opsLimit: $opsLimit",
e,
s,
);
}
memLimit = (memLimit / 2).round();
opsLimit = opsLimit * 2;

View File

@@ -0,0 +1,31 @@
import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:logging/logging.dart';
late DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
// https://gist.github.com/adamawolf/3048717
late Set<String> iOSLowEndMachineCodes = <String>{
"iPhone5,2",
"iPhone5,3",
"iPhone5,4",
"iPhone6,1",
"iPhone6,2",
"iPhone7,2",
"iPhone7,1",
};
Future<bool> isLowSpecDevice() async {
try {
if (Platform.isIOS) {
final IosDeviceInfo iosInfo = await deviceInfoPlugin.iosInfo;
debugPrint("ios utc name ${iosInfo.utsname.machine}");
return iOSLowEndMachineCodes.contains(iosInfo.utsname.machine);
}
} catch (e) {
Logger("device_info").severe("deviceSpec check failed", e);
}
return false;
}

View File

@@ -6,18 +6,20 @@ import FlutterMacOS
import Foundation
import connectivity_macos
import device_info_plus
import flutter_local_notifications
import flutter_secure_storage_macos
import package_info_plus_macos
import path_provider_macos
import path_provider_foundation
import sentry_flutter
import share_plus_macos
import shared_preferences_macos
import shared_preferences_foundation
import sqflite
import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
FlutterSecureStorageMacosPlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStorageMacosPlugin"))
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))

View File

@@ -7,7 +7,7 @@ packages:
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
version: "40.0.0"
version: "47.0.0"
adaptive_theme:
dependency: "direct main"
description:
@@ -21,21 +21,21 @@ packages:
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
version: "4.1.0"
version: "4.7.0"
archive:
dependency: transitive
description:
name: archive
url: "https://pub.dartlang.org"
source: hosted
version: "3.3.1"
version: "3.3.6"
args:
dependency: transitive
description:
name: args
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.1"
version: "2.3.2"
async:
dependency: transitive
description:
@@ -63,14 +63,14 @@ packages:
name: bloc
url: "https://pub.dartlang.org"
source: hosted
version: "8.0.3"
version: "8.1.0"
bloc_test:
dependency: "direct dev"
description:
name: bloc_test
url: "https://pub.dartlang.org"
source: hosted
version: "9.0.3"
version: "9.1.0"
boolean_selector:
dependency: transitive
description:
@@ -84,14 +84,14 @@ packages:
name: build
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.0"
version: "2.3.1"
build_config:
dependency: transitive
description:
name: build_config
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
version: "1.1.1"
build_daemon:
dependency: transitive
description:
@@ -105,21 +105,21 @@ packages:
name: build_resolvers
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.9"
version: "2.0.10"
build_runner:
dependency: "direct dev"
description:
name: build_runner
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.11"
version: "2.3.0"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
url: "https://pub.dartlang.org"
source: hosted
version: "7.2.3"
version: "7.2.7"
built_collection:
dependency: transitive
description:
@@ -133,7 +133,7 @@ packages:
name: built_value
url: "https://pub.dartlang.org"
source: hosted
version: "8.3.2"
version: "8.4.3"
characters:
dependency: transitive
description:
@@ -147,7 +147,7 @@ packages:
name: checked_yaml
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
version: "2.0.2"
clipboard:
dependency: "direct main"
description:
@@ -168,7 +168,7 @@ packages:
name: code_builder
url: "https://pub.dartlang.org"
source: hosted
version: "4.1.0"
version: "4.4.0"
collection:
dependency: "direct main"
description:
@@ -224,14 +224,21 @@ packages:
name: convert
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.2"
version: "3.1.1"
coverage:
dependency: transitive
description:
name: coverage
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.2"
version: "1.6.2"
cross_file:
dependency: transitive
description:
name: cross_file
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.3+4"
crypto:
dependency: transitive
description:
@@ -259,7 +266,7 @@ packages:
name: dart_style
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.3"
version: "2.2.4"
dbus:
dependency: transitive
description:
@@ -267,20 +274,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.7.8"
device_info:
device_info_plus:
dependency: "direct main"
description:
name: device_info
name: device_info_plus
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
device_info_platform_interface:
version: "8.0.0"
device_info_plus_platform_interface:
dependency: transitive
description:
name: device_info_platform_interface
name: device_info_plus_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
version: "7.0.0"
diff_match_patch:
dependency: transitive
description:
@@ -301,7 +308,7 @@ packages:
name: dotted_border
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0+2"
version: "2.0.0+3"
email_validator:
dependency: "direct main"
description:
@@ -350,14 +357,14 @@ packages:
name: file
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.2"
version: "6.1.4"
file_picker:
dependency: "direct main"
description:
name: file_picker
url: "https://pub.dartlang.org"
source: hosted
version: "5.2.4"
version: "5.2.5"
fixnum:
dependency: transitive
description:
@@ -383,28 +390,28 @@ packages:
name: flutter_animation_progress_bar
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.1"
version: "2.3.1"
flutter_bloc:
dependency: "direct main"
description:
name: flutter_bloc
url: "https://pub.dartlang.org"
source: hosted
version: "8.0.1"
version: "8.1.1"
flutter_email_sender:
dependency: "direct main"
description:
name: flutter_email_sender
url: "https://pub.dartlang.org"
source: hosted
version: "5.1.0"
version: "5.2.0"
flutter_inappwebview:
dependency: "direct main"
description:
name: flutter_inappwebview
url: "https://pub.dartlang.org"
source: hosted
version: "5.7.1"
version: "5.7.2+3"
flutter_launcher_icons:
dependency: "direct main"
description:
@@ -418,14 +425,14 @@ packages:
name: flutter_local_notifications
url: "https://pub.dartlang.org"
source: hosted
version: "12.0.3"
version: "12.0.4"
flutter_local_notifications_linux:
dependency: transitive
description:
name: flutter_local_notifications_linux
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
version: "2.0.0"
flutter_local_notifications_platform_interface:
dependency: transitive
description:
@@ -444,7 +451,7 @@ packages:
name: flutter_native_splash
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.13"
version: "2.2.16"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
@@ -458,42 +465,42 @@ packages:
name: flutter_secure_storage
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.0"
version: "6.1.0"
flutter_secure_storage_linux:
dependency: transitive
description:
name: flutter_secure_storage_linux
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
version: "1.1.2"
flutter_secure_storage_macos:
dependency: transitive
description:
name: flutter_secure_storage_macos
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
version: "1.1.2"
flutter_secure_storage_platform_interface:
dependency: transitive
description:
name: flutter_secure_storage_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
version: "1.0.1"
flutter_secure_storage_web:
dependency: transitive
description:
name: flutter_secure_storage_web
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
version: "1.1.1"
flutter_secure_storage_windows:
dependency: transitive
description:
name: flutter_secure_storage_windows
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.2"
version: "1.1.3"
flutter_slidable:
dependency: "direct main"
description:
@@ -527,20 +534,13 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_windowmanager:
dependency: "direct main"
description:
name: flutter_windowmanager
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0"
fluttertoast:
dependency: "direct main"
description:
name: fluttertoast
url: "https://pub.dartlang.org"
source: hosted
version: "8.1.1"
version: "8.1.2"
frontend_server_client:
dependency: transitive
description:
@@ -554,7 +554,7 @@ packages:
name: glob
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
version: "2.1.1"
google_nav_bar:
dependency: "direct main"
description:
@@ -568,7 +568,7 @@ packages:
name: graphs
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
version: "2.2.0"
hex:
dependency: transitive
description:
@@ -596,21 +596,21 @@ packages:
name: http_multi_server
url: "https://pub.dartlang.org"
source: hosted
version: "3.2.0"
version: "3.2.1"
http_parser:
dependency: transitive
description:
name: http_parser
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.1"
version: "4.0.2"
image:
dependency: transitive
description:
name: image
url: "https://pub.dartlang.org"
source: hosted
version: "3.2.2"
version: "3.3.0"
intl:
dependency: "direct main"
description:
@@ -624,7 +624,7 @@ packages:
name: io
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
version: "1.0.4"
js:
dependency: transitive
description:
@@ -638,14 +638,14 @@ packages:
name: json_annotation
url: "https://pub.dartlang.org"
source: hosted
version: "4.5.0"
version: "4.7.0"
json_serializable:
dependency: "direct dev"
description:
name: json_serializable
url: "https://pub.dartlang.org"
source: hosted
version: "6.2.0"
version: "6.5.4"
lints:
dependency: "direct dev"
description:
@@ -666,7 +666,7 @@ packages:
name: logging
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
version: "1.1.1"
matcher:
dependency: transitive
description:
@@ -694,7 +694,7 @@ packages:
name: mime
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
version: "1.0.4"
mocktail:
dependency: "direct dev"
description:
@@ -723,27 +723,27 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
open_file:
open_filex:
dependency: "direct main"
description:
name: open_file
name: open_filex
url: "https://pub.dartlang.org"
source: hosted
version: "3.2.1"
version: "4.3.2"
otp:
dependency: "direct main"
description:
name: otp
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.1"
version: "3.1.3"
package_config:
dependency: transitive
description:
name: package_config
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
version: "2.1.0"
package_info_plus:
dependency: "direct main"
description:
@@ -778,7 +778,7 @@ packages:
name: package_info_plus_web
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
version: "1.0.6"
package_info_plus_windows:
dependency: transitive
description:
@@ -820,21 +820,21 @@ packages:
name: path_provider
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.11"
version: "2.0.12"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.20"
path_provider_ios:
version: "2.0.22"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_ios
name: path_provider_foundation
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.11"
version: "2.1.1"
path_provider_linux:
dependency: transitive
description:
@@ -842,20 +842,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.7"
path_provider_macos:
dependency: transitive
description:
name: path_provider_macos
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.6"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.4"
version: "2.0.5"
path_provider_windows:
dependency: transitive
description:
@@ -869,7 +862,7 @@ packages:
name: petitparser
url: "https://pub.dartlang.org"
source: hosted
version: "5.0.0"
version: "5.1.0"
pinput:
dependency: "direct main"
description:
@@ -904,7 +897,7 @@ packages:
name: pool
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.0"
version: "1.5.1"
process:
dependency: transitive
description:
@@ -918,21 +911,21 @@ packages:
name: provider
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.3"
version: "6.0.5"
pub_semver:
dependency: transitive
description:
name: pub_semver
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
version: "2.1.3"
pubspec_parse:
dependency: transitive
description:
name: pubspec_parse
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.2.1"
qr_code_scanner:
dependency: "direct main"
description:
@@ -946,28 +939,28 @@ packages:
name: sentry
url: "https://pub.dartlang.org"
source: hosted
version: "6.15.1"
version: "6.19.0"
sentry_flutter:
dependency: "direct main"
description:
name: sentry_flutter
url: "https://pub.dartlang.org"
source: hosted
version: "6.15.1"
version: "6.19.0"
share_plus:
dependency: "direct main"
description:
name: share_plus
url: "https://pub.dartlang.org"
source: hosted
version: "4.4.0"
version: "4.5.3"
share_plus_linux:
dependency: transitive
description:
name: share_plus_linux
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
version: "3.0.1"
share_plus_macos:
dependency: transitive
description:
@@ -981,14 +974,14 @@ packages:
name: share_plus_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.3"
version: "3.2.0"
share_plus_web:
dependency: transitive
description:
name: share_plus_web
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
version: "3.1.0"
share_plus_windows:
dependency: transitive
description:
@@ -1002,35 +995,28 @@ packages:
name: shared_preferences
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.15"
version: "2.0.17"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.13"
shared_preferences_ios:
version: "2.0.15"
shared_preferences_foundation:
dependency: transitive
description:
name: shared_preferences_ios
name: shared_preferences_foundation
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
version: "2.1.3"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
shared_preferences_macos:
dependency: transitive
description:
name: shared_preferences_macos
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.4"
version: "2.1.3"
shared_preferences_platform_interface:
dependency: transitive
description:
@@ -1051,35 +1037,35 @@ packages:
name: shared_preferences_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
version: "2.1.3"
shelf:
dependency: transitive
description:
name: shelf
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
version: "1.4.0"
shelf_packages_handler:
dependency: transitive
description:
name: shelf_packages_handler
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
version: "3.0.1"
shelf_static:
dependency: transitive
description:
name: shelf_static
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.1"
shelf_web_socket:
dependency: transitive
description:
name: shelf_web_socket
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
version: "1.0.3"
sky_engine:
dependency: transitive
description: flutter
@@ -1091,28 +1077,28 @@ packages:
name: source_gen
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.2"
version: "1.2.6"
source_helper:
dependency: transitive
description:
name: source_helper
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.2"
version: "1.3.3"
source_map_stack_trace:
dependency: transitive
description:
name: source_map_stack_trace
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
version: "2.1.1"
source_maps:
dependency: transitive
description:
name: source_maps
url: "https://pub.dartlang.org"
source: hosted
version: "0.10.10"
version: "0.10.11"
source_span:
dependency: transitive
description:
@@ -1126,14 +1112,14 @@ packages:
name: sqflite
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
version: "2.2.4+1"
sqflite_common:
dependency: transitive
description:
name: sqflite_common
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.0"
version: "2.4.2+2"
stack_trace:
dependency: transitive
description:
@@ -1161,7 +1147,7 @@ packages:
name: stream_transform
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.1.0"
string_scanner:
dependency: transitive
description:
@@ -1175,7 +1161,7 @@ packages:
name: synchronized
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0+3"
version: "3.0.1"
term_glyph:
dependency: transitive
description:
@@ -1210,14 +1196,14 @@ packages:
name: timezone
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.0"
version: "0.9.1"
timing:
dependency: transitive
description:
name: timing
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
version: "1.0.1"
typed_data:
dependency: transitive
description:
@@ -1238,63 +1224,63 @@ packages:
name: url_launcher
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.5"
version: "6.1.8"
url_launcher_android:
dependency: transitive
description:
name: url_launcher_android
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.19"
version: "6.0.23"
url_launcher_ios:
dependency: transitive
description:
name: url_launcher_ios
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.17"
version: "6.0.18"
url_launcher_linux:
dependency: transitive
description:
name: url_launcher_linux
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
version: "3.0.2"
url_launcher_macos:
dependency: transitive
description:
name: url_launcher_macos
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
version: "3.0.2"
url_launcher_platform_interface:
dependency: transitive
description:
name: url_launcher_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
version: "2.1.1"
url_launcher_web:
dependency: transitive
description:
name: url_launcher_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.13"
version: "2.0.14"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
version: "3.0.3"
uuid:
dependency: "direct main"
description:
name: uuid
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.6"
version: "3.0.7"
vector_math:
dependency: transitive
description:
@@ -1308,42 +1294,42 @@ packages:
name: vm_service
url: "https://pub.dartlang.org"
source: hosted
version: "8.3.0"
version: "9.4.0"
watcher:
dependency: transitive
description:
name: watcher
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
version: "1.0.2"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.0"
version: "2.3.0"
webkit_inspection_protocol:
dependency: transitive
description:
name: webkit_inspection_protocol
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.2.0"
win32:
dependency: transitive
description:
name: win32
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.2"
version: "3.1.3"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0+2"
version: "0.2.0+3"
xml:
dependency: transitive
description:
@@ -1360,4 +1346,4 @@ packages:
version: "3.1.1"
sdks:
dart: ">=2.18.0 <3.0.0"
flutter: ">=3.3.0-0"
flutter: ">=3.3.0"

View File

@@ -1,6 +1,6 @@
name: ente_auth
description: ente two-factor authenticator
version: 1.0.22+22
version: 1.0.28+28
publish_to: none
environment:
@@ -16,7 +16,7 @@ dependencies:
confetti: ^0.7.0
connectivity: ^3.0.3
cupertino_icons: ^1.0.0
device_info: ^2.0.2
device_info_plus: ^8.0.0
dio: ^4.0.6
dotted_border: ^2.0.0+2
email_validator: ^2.0.1
@@ -42,7 +42,6 @@ dependencies:
git:
url: https://github.com/ente-io/flutter_sodium.git
flutter_speed_dial: ^6.2.0
flutter_windowmanager: ^0.2.0
fluttertoast: ^8.1.1
google_nav_bar: ^5.0.5 #supported
http: ^0.13.4
@@ -51,7 +50,7 @@ dependencies:
local_auth: ^1.1.5
logging: ^1.0.1
move_to_background: ^1.0.2
open_file: ^3.2.1
open_filex: ^4.3.2
otp: ^3.1.1
package_info_plus: ^1.0.1
password_strength: ^0.2.0

View File

@@ -0,0 +1,13 @@
import 'package:ente_auth/models/code.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
test("parseCodeFromRawData", () {
final code1 = Code.fromRawData(
"otpauth://totp/example%20finance%3Aee%40ff.gg?secret=ASKZNWOU6SVYAMVS",
);
expect(code1.issuer, "example finance");
expect(code1.account, "ee@ff.gg");
expect(code1.secret, "ASKZNWOU6SVYAMVS");
});
}