Compare commits

..

6 Commits

Author SHA1 Message Date
Prateek Sunal
40d4b21be9 chore: add heavy logging 2025-08-19 14:10:12 +05:30
Prateek Sunal
7027edb2d1 Merge remote-tracking branch 'origin/main' into bg-ml 2025-08-19 12:48:27 +05:30
Prateek Sunal
831720a49d Merge remote-tracking branch 'origin/decoded_image_refactor' into bg-ml 2025-08-19 12:48:20 +05:30
laurenspriem
24b88a186c Decode image in background using image pkg 2025-08-19 11:05:39 +05:30
Prateek Sunal
ecf58c175b fix: add more things for testing 2025-08-13 19:51:05 +05:30
Prateek Sunal
cc0198f879 fix: add more logs for testing 2025-08-13 14:37:23 +05:30
772 changed files with 81348 additions and 25949 deletions

View File

@@ -8,7 +8,7 @@ on:
env:
FLUTTER_VERSION: "3.32.8"
RUST_VERSION: "1.86.0"
RUST_VERSION: "1.85.1"
permissions:
contents: read
@@ -27,38 +27,6 @@ jobs:
with:
submodules: recursive
- name: Free up disk space
run: |
echo "Initial disk usage:"
df -h /
# Get available space in KB
INITIAL=$(df / | awk 'NR==2 {print $4}')
echo -e "\n=== Removing .NET SDK (~20-25GB) ==="
BEFORE=$(df / | awk 'NR==2 {print $4}')
START=$(date +%s)
sudo rm -rf /usr/share/dotnet
END=$(date +%s)
AFTER=$(df / | awk 'NR==2 {print $4}')
FREED=$(( (AFTER - BEFORE) / 1048576 )) # Convert KB to GB
echo "Time: $((END-START))s | Freed: ${FREED}GB"
echo -e "\n=== Removing cached tools (~5-10GB) ==="
BEFORE=$(df / | awk 'NR==2 {print $4}')
START=$(date +%s)
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
END=$(date +%s)
AFTER=$(df / | awk 'NR==2 {print $4}')
FREED=$(( (AFTER - BEFORE) / 1048576 ))
echo "Time: $((END-START))s | Freed: ${FREED}GB"
echo -e "\n=== Final Summary ==="
FINAL=$(df / | awk 'NR==2 {print $4}')
TOTAL_FREED=$(( (FINAL - INITIAL) / 1048576 ))
echo "Total space freed: ${TOTAL_FREED}GB"
echo "Final disk usage:"
df -h /
- name: Setup JDK 17
uses: actions/setup-java@v1
with:
@@ -71,12 +39,14 @@ jobs:
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Install Rust ${{ env.RUST_VERSION }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.RUST_VERSION }}
- name: Install Flutter Rust Bridge
run: cargo install flutter_rust_bridge_codegen
- name: Generate Rust bindings
run: flutter_rust_bridge_codegen generate
- name: Increment version code for build
run: |
CURRENT_VERSION=$(grep '^version:' pubspec.yaml | sed 's/version: //')

View File

@@ -0,0 +1,77 @@
name: "Old Internal release (photos)"
on:
workflow_dispatch: # Allow manually running the action
env:
FLUTTER_VERSION: "3.32.8"
RUST_VERSION: "1.85.1"
permissions:
contents: write
jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
working-directory: mobile/apps/photos
steps:
- name: Checkout code and submodules
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup JDK 17
uses: actions/setup-java@v1
with:
java-version: 17
- name: Install Flutter ${{ env.FLUTTER_VERSION }}
uses: subosito/flutter-action@v2
with:
channel: "stable"
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Install Rust ${{ env.RUST_VERSION }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.RUST_VERSION }}
- name: Install Flutter Rust Bridge
run: cargo install flutter_rust_bridge_codegen
- name: Setup keys
uses: timheuer/base64-to-file@v1
with:
fileName: "keystore/ente_photos_key.jks"
encodedString: ${{ secrets.SIGNING_KEY_PHOTOS }}
- name: Build PlayStore AAB
run: |
flutter build appbundle --dart-define=cronetHttpNoPlay=true --release --flavor playstore
env:
SIGNING_KEY_PATH: "/home/runner/work/_temp/keystore/ente_photos_key.jks"
SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS_PHOTOS }}
SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD_PHOTOS }}
SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD_PHOTOS }}
- name: Upload AAB to PlayStore
uses: r0adkll/upload-google-play@v1
with:
serviceAccountJsonPlainText: ${{ secrets.SERVICE_ACCOUNT_JSON }}
packageName: io.ente.photos
releaseFiles: mobile/apps/photos/build/app/outputs/bundle/playstoreRelease/app-playstore-release.aab
track: internal
- name: Notify Discord
uses: sarisia/actions-status-discord@v1
with:
webhook: ${{ secrets.DISCORD_INTERNAL_RELEASE_WEBHOOK }}
nodetail: true
title: "🏆 Internal release Photos (Branch: ${{ github.ref_name }})"
description: "[Download](https://play.google.com/store/apps/details?id=io.ente.photos)"
color: 0x00ff00

View File

@@ -9,7 +9,6 @@ on:
env:
FLUTTER_VERSION: "3.32.8"
RUST_VERSION: "1.86.0"
permissions:
contents: read
@@ -32,18 +31,7 @@ jobs:
channel: "stable"
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- run: flutter pub get
- name: Install Rust ${{ env.RUST_VERSION }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.RUST_VERSION }}
- name: Install Flutter Rust Bridge
run: cargo install flutter_rust_bridge_codegen
- name: Generate Rust bindings
run: flutter_rust_bridge_codegen generate
- run: flutter analyze --no-fatal-infos

View File

@@ -28,38 +28,6 @@ jobs:
with:
submodules: recursive
- name: Free up disk space
run: |
echo "Initial disk usage:"
df -h /
# Get available space in KB
INITIAL=$(df / | awk 'NR==2 {print $4}')
echo -e "\n=== Removing .NET SDK (~20-25GB) ==="
BEFORE=$(df / | awk 'NR==2 {print $4}')
START=$(date +%s)
sudo rm -rf /usr/share/dotnet
END=$(date +%s)
AFTER=$(df / | awk 'NR==2 {print $4}')
FREED=$(( (AFTER - BEFORE) / 1048576 )) # Convert KB to GB
echo "Time: $((END-START))s | Freed: ${FREED}GB"
echo -e "\n=== Removing cached tools (~5-10GB) ==="
BEFORE=$(df / | awk 'NR==2 {print $4}')
START=$(date +%s)
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
END=$(date +%s)
AFTER=$(df / | awk 'NR==2 {print $4}')
FREED=$(( (AFTER - BEFORE) / 1048576 ))
echo "Time: $((END-START))s | Freed: ${FREED}GB"
echo -e "\n=== Final Summary ==="
FINAL=$(df / | awk 'NR==2 {print $4}')
TOTAL_FREED=$(( (FINAL - INITIAL) / 1048576 ))
echo "Total space freed: ${TOTAL_FREED}GB"
echo "Final disk usage:"
df -h /
- name: Setup JDK 17
uses: actions/setup-java@v1
with:
@@ -72,12 +40,6 @@ jobs:
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Install Flutter Rust Bridge
run: cargo install flutter_rust_bridge_codegen
- name: Generate Rust bindings
run: flutter_rust_bridge_codegen generate
- name: Setup keys
uses: timheuer/base64-to-file@v1
with:

View File

@@ -142,22 +142,6 @@ var _updateFreeUserStorage = &cobra.Command{
},
}
var _sendMail = &cobra.Command{
Use: "send-mail <to-email> <from-email> <from-name>",
Args: cobra.ExactArgs(3),
Short: "Sends a test mail via the admin api",
RunE: func(cmd *cobra.Command, args []string) error {
recoverWithLog()
var flags = &model.AdminActionForUser{}
cmd.Flags().VisitAll(func(f *pflag.Flag) {
if f.Name == "admin-user" {
flags.AdminEmail = f.Value.String()
}
})
return ctrl.SendTestMail(context.Background(), *flags, args[0], args[1], args[2])
},
}
func init() {
rootCmd.AddCommand(_adminCmd)
_ = _userDetailsCmd.MarkFlagRequired("admin-user")
@@ -175,6 +159,5 @@ func init() {
_updateFreeUserStorage.Flags().StringP("user", "u", "", "The email of the user to update subscription for. (required)")
// add a flag with no value --no-limit
_updateFreeUserStorage.Flags().String("no-limit", "True", "When true, sets 100TB as storage limit, and expiry to current date + 100 years")
_sendMail.Flags().StringP("admin-user", "a", "", "The email of the admin user. ")
_adminCmd.AddCommand(_userDetailsCmd, _disable2faCmd, _disablePasskeyCmd, _updateFreeUserStorage, _listUsers, _deleteUser, _sendMail)
_adminCmd.AddCommand(_userDetailsCmd, _disable2faCmd, _disablePasskeyCmd, _updateFreeUserStorage, _listUsers, _deleteUser)
}

View File

@@ -139,28 +139,5 @@ func (c *Client) UpdateFreePlanSub(ctx context.Context, userDetails *models.User
}
}
return nil
}
func (c *Client) SendTestMail(ctx context.Context, toEmail, fromEmail, fromName string) error {
body := map[string]interface{}{
"to": []string{toEmail},
"fromName": fromName,
"fromEmail": fromEmail,
"subject": "Test mail from Ente",
"body": "This is a test mail from Ente",
}
r, err := c.restClient.R().
SetContext(ctx).
SetBody(body).
Post("/admin/mail")
if err != nil {
return err
}
if r.IsError() {
return &ApiError{
StatusCode: r.StatusCode(),
Message: r.String(),
}
}
return nil
}

View File

@@ -156,23 +156,6 @@ func (c *ClICtrl) UpdateFreeStorage(ctx context.Context, params model.AdminActio
return nil
}
func (c *ClICtrl) SendTestMail(ctx context.Context, params model.AdminActionForUser, to, from, fromName string) error {
accountCtx, err := c.buildAdminContext(ctx, params.AdminEmail)
if err != nil {
return err
}
err = c.Client.SendTestMail(accountCtx, to, from, fromName)
if err != nil {
if apiErr, ok := err.(*api.ApiError); ok && apiErr.StatusCode == 400 && strings.Contains(apiErr.Message, "Token is too old") {
fmt.Printf("Error: old admin token, please re-authenticate using `ente account add` \n")
return nil
}
return err
}
fmt.Printf("Successfully sent test email to %s\n", to)
return nil
}
func (c *ClICtrl) buildAdminContext(ctx context.Context, adminEmail string) (context.Context, error) {
accounts, err := c.GetAccounts(ctx)
if err != nil {

View File

@@ -2,8 +2,6 @@
## v1.7.15 (Unreleased)
- Custom domains.
- Support Czech translations.
- .
## v1.7.14

View File

@@ -8,12 +8,6 @@ description: Guide to configuring Ente CLI for Self Hosted Instance
If you are self-hosting, you can configure Ente CLI to export data & perform
basic administrative actions.
::: tip Installing Ente CLI
For instructions on installing the Ente CLI, see the [README available on Github](https://github.com/ente-io/ente/tree/main/cli/README.md).
:::
## Step 1: Configure endpoint
To do this, first configure the CLI to use your server's endpoint.

View File

@@ -22,7 +22,8 @@ can achieve this the following steps:
# Change the DB name and DB user name if you use different
# values.
# If using Docker
docker exec -it <postgres-ente-container-name> sh
docker exec -it <postgres-ente-container-name>
psql -U pguser -d ente_db
# Or when using psql directly

View File

@@ -171,8 +171,6 @@ smtp:
email:
# Optional name for sender
sender-name:
# Optional encryption
encryption:
```
| Variable | Description | Default |
@@ -183,7 +181,6 @@ smtp:
| `smtp.password` | SMTP auth password | |
| `smtp.email` | Sender email address | |
| `smtp.sender-name` | Custom name for email sender | |
| `smtp.encryption` | Encryption method (tls, ssl) | |
| `transmail.key` | Zeptomail API key | |
### WebAuthn Passkey Support

View File

@@ -46,7 +46,7 @@ If running Museum without Docker, the code should be visible in the terminal
# Change the DB name and DB user name if you use different
# values.
# If using Docker docker exec -it <postgres-ente-container-name> sh
# If using Docker docker exec -it <postgres-ente-container-name>
psql -U pguser -d ente_db
# Or when using psql directly

45
mobile/.gitignore vendored
View File

@@ -1,45 +0,0 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
melos_*.iml
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release

View File

@@ -1,72 +0,0 @@
# For more linters, we can check https://dart-lang.github.io/linter/lints/index.html
# or https://pub.dev/packages/lint (Effective dart)
# use "flutter analyze ." or "dart analyze ." for running lint checks
include: package:flutter_lints/flutter.yaml
linter:
rules:
# Ref https://github.com/flutter/packages/blob/master/packages/flutter_lints/lib/flutter.yaml
# Ref https://dart-lang.github.io/linter/lints/
- avoid_print
- avoid_unnecessary_containers
- avoid_web_libraries_in_flutter
- no_logic_in_create_state
- prefer_const_constructors
- prefer_const_constructors_in_immutables
- prefer_const_declarations
- prefer_const_literals_to_create_immutables
- prefer_final_locals
- require_trailing_commas
- sized_box_for_whitespace
- use_full_hex_values_for_flutter_colors
- use_key_in_widget_constructors
- cancel_subscriptions
- avoid_empty_else
- exhaustive_cases
# just style suggestions
- sort_pub_dependencies
- use_rethrow_when_possible
- prefer_double_quotes
- directives_ordering
- always_use_package_imports
- sort_child_properties_last
- unawaited_futures
analyzer:
errors:
avoid_empty_else: error
exhaustive_cases: error
curly_braces_in_flow_control_structures: error
directives_ordering: error
require_trailing_commas: error
always_use_package_imports: warning
prefer_final_fields: error
unused_import: error
camel_case_types: error
prefer_is_empty: warning
use_rethrow_when_possible: info
unused_field: warning
use_key_in_widget_constructors: warning
sort_child_properties_last: warning
sort_pub_dependencies: warning
library_private_types_in_public_api: warning
constant_identifier_names: ignore
prefer_const_constructors: warning
prefer_const_declarations: warning
prefer_const_constructors_in_immutables: warning
prefer_final_locals: warning
unnecessary_const: error
cancel_subscriptions: error
unrelated_type_equality_checks: error
unnecessary_cast: info
unawaited_futures: warning # convert to warning after fixing existing issues
invalid_dependency: info
use_build_context_synchronously: ignore # experimental lint, requires many changes
prefer_interpolation_to_compose_strings: ignore # later too many warnings
prefer_double_quotes: ignore # too many warnings
avoid_renaming_method_parameters: ignore # incorrect warnings for `equals` overrides

View File

@@ -382,11 +382,6 @@
{
"title": "CoinDCX"
},
{
"title": "CoinTracking",
"slug": "cointracking",
"altNames": ["cointracking.info", "Coin Tracking"]
},
{
"title": "colorado",
"altNames": [
@@ -740,11 +735,6 @@
{
"title": "Hivelocity"
},
{
"title": "HRDocumentBox",
"slug": "hrdocumentbox",
"altNames": ["HRDocumentBox", "HR Document Box"]
},
{
"title": "HSA Bank",
"slug": "hsa_bank",
@@ -1050,13 +1040,6 @@
"MistralAI"
]
},
{
"title": "Mobile01",
"slug": "mobile01",
"altNames": [
"M01"
]
},
{
"title": "Mozilla"
},
@@ -1236,12 +1219,6 @@
"title": "Parqet",
"slug": "parqet"
},
{
"title": "Parallels",
"slug": "parallels",
"hex": "#E61E25",
"altNames": ["Parallels Desktop", "Parallels VM"]
},
{
"title": "Parsec"
},
@@ -1796,11 +1773,6 @@
"uollet.com.br"
]
},
{
"title": "VHV",
"slug": "vhv",
"altNames": ["VHV", "VHV Versicherung"]
},
{
"title": "Vikunja"
},

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1220.8 227.9" style="enable-background:new 0 0 1220.8 227.9;" xml:space="preserve">
<style type="text/css">
.st0{fill:#0D253E;}
.st1{fill:#008AFB;}
</style>
<title>CoinTracking light</title>
<g id="Layer_2_1_">
<g id="Layer_1-2">
<path class="st0" d="M198.1,167c-30.2,0-54.7-24.5-54.7-54.7s24.5-54.7,54.7-54.7s54.7,24.5,54.7,54.7l0,0 C252.8,142.5,228.3,167,198.1,167z M198.1,81.6c-17,0-30.7,13.7-30.7,30.7s13.7,30.7,30.7,30.7s30.7-13.7,30.7-30.7l0,0 C228.8,95.4,215,81.6,198.1,81.6z"/>
<path class="st0" d="M292.2,59.5h-23.6v107.9h23.6V59.5z"/>
<path class="st0" d="M339.5,167.4h-23.8V59.5h23.8v16.2c6.2-12.5,21-18.5,33-18.5c26.1,0,41.1,16.9,41.1,47.3v62.8h-23.8v-60.1 c0-17.1-8.8-26.8-22.6-26.8c-14.1,0-27.7,7.6-27.7,28.9V167.4z"/>
<path class="st1" d="M390.6,8.2h151.7v22.9h-65.9v136.3h-25V31.1h-60.9V8.2H390.6z"/>
<path class="st1" d="M540.3,167.4h-23.8V59.5h23.8V79c7.4-13.5,15.4-19.5,29.6-21.8c7.5-1.2,15.7,1.8,19.2,4.2l-3.9,22 c-4.9-2.5-10.4-3.8-15.9-3.7c-20.3,0-28.9,20.3-28.9,49L540.3,167.4L540.3,167.4z"/>
<path class="st1" d="M680.7,151.9c-7.2,11.8-22.9,17.8-36.3,17.8c-29.1,0-54.8-21.9-54.8-56.4s25.6-56.1,54.8-56.1 c12.9,0,28.9,5.3,36.3,17.5V59.5h23.6v107.9h-23.6V151.9z M647.2,146.6c17.6,0,33.3-12.2,33.3-33.5s-17.1-32.8-33.3-32.8 c-18,0-33,12.9-33,32.8S629.2,146.6,647.2,146.6L647.2,146.6z"/>
<path class="st1" d="M778.4,57.2c17.1,0,32.6,6.7,42.7,18.7l-18.5,14.8c-5.8-6.7-14.8-10.4-24.3-10.4c-18,0-34,12.7-34,32.8 s15.9,33.7,34,33.7c9.5,0,18.5-3.9,24.3-10.6l18.7,14.6c-10.2,12-25.6,18.9-43,18.9c-31,0-57.5-22.4-57.5-56.6 S747.4,57.2,778.4,57.2z"/>
<path class="st1" d="M860.3,117.2v50.1h-23.6V0.8h23.6V95l34.2-35.6h31.9l-46,46.9l56.4,61h-30.5L860.3,117.2z"/>
<path class="st1" d="M967.4,59.5h-23.6v107.9h23.6V59.5z"/>
<path class="st1" d="M1014.7,167.4h-23.8V59.5h23.8v16.2c6.2-12.5,21-18.5,33-18.5c26.1,0,41.1,16.9,41.1,47.3v62.8H1065v-60.1 c0-17.1-8.8-26.8-22.6-26.8c-14.1,0-27.7,7.6-27.7,28.9V167.4z"/>
<path class="st1" d="M1220.2,111.5c0-12.3-4.5-24.2-12.5-33.6l13-17.1l-19.6-13l-11.9,15.7c-8.3-4.1-17.5-6.2-26.8-6.2 c-31.9,0-57.8,24.4-57.8,54.3s25.9,54.3,57.8,54.3c20.2,0,34.2,10.2,34.2,19.3s-14.1,19.3-34.2,19.3s-34.2-10.2-34.2-19.3h-23.6 c0,24,25.4,42.9,57.8,42.9s57.8-18.8,57.8-42.9c0-13.2-7.7-24.8-19.9-32.6C1212.5,142.5,1220.2,127.8,1220.2,111.5z M1128.2,111.5 c0-16.9,15.4-30.7,34.2-30.7s34.2,13.8,34.2,30.7s-15.4,30.7-34.2,30.7S1128.2,128.4,1128.2,111.5L1128.2,111.5z"/>
<path class="st0" d="M81.4,170.5C36.4,170.5,0,134,0,89c0-21.6,8.6-42.3,23.9-57.6c31.8-31.8,83.4-31.8,115.2,0l0,0l-17.7,17.7 C99.3,27,63.6,27,41.5,49.1s-22.1,57.8,0,79.9s57.8,22.1,79.9,0l17.7,17.7C123.8,162,103.1,170.6,81.4,170.5z"/>
<circle class="st0" cx="280.7" cy="15.5" r="15.5"/>
<circle class="st1" cx="954.7" cy="15.5" r="15.5"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -1,26 +0,0 @@
<?xml version="1.0"?>
<svg width="320" height="280" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" version="1.1">
<g class="layer">
<title>Layer 1</title>
<g id="Layer1000">
<g id="Layer1002">
<g id="Layer1003">
<path d="m123.08,34.29c-66.43,0 -120.27,53.85 -120.27,120.27c0,66.43 53.85,120.27 120.27,120.27c66.47,0 120.32,-53.85 120.32,-120.27c0,-66.43 -53.85,-120.27 -120.32,-120.27zm0,215.67c-52.67,0 -95.36,-42.73 -95.36,-95.4c0,-52.67 42.68,-95.4 95.36,-95.4c52.72,0 95.4,42.73 95.4,95.4c0,52.67 -42.68,95.4 -95.4,95.4z" fill="#2a5e00" fill-rule="evenodd" id="path7"/>
<g id="Layer1004">
<g id="Layer1005">
<path d="m138.72,146.29l59.61,-41.47l7.78,33.7l-67.39,7.78z" fill="#2a5e00" fill-rule="evenodd" id="path8"/>
<path d="m110.88,146.29l-59.61,-41.47l-7.78,33.7l67.39,7.78z" fill="#2a5e00" fill-rule="evenodd" id="path9"/>
</g>
<path d="m43.95,192.02l74.62,49.75l87.12,-78.8l-161.75,29.05z" fill="#2a5e00" fill-rule="evenodd" id="path10"/>
</g>
<path d="m94.24,59.29l-30.48,-55.1l54.26,33.24l-23.79,21.86z" fill="#2a5e00" fill-rule="evenodd" id="path11"/>
<path d="m202.64,78.1l30.43,-55.1l-54.22,33.24l23.79,21.86z" fill="#2a5e00" fill-rule="evenodd" id="path12"/>
</g>
<path d="m275.63,274.67l29.35,0l0,-240.76l-29.35,0l0,240.76z" fill="#2a5e00" fill-rule="evenodd" id="path13"/>
<path d="m317.94,125.93c0,15.3 -12.33,27.63 -27.63,27.63c-15.26,0 -27.63,-12.33 -27.63,-27.63c0,-15.26 12.37,-27.63 27.63,-27.63c15.3,0 27.63,12.37 27.63,27.63z" fill="#2a5e00" fill-rule="evenodd" id="path14"/>
<path d="m288.84,33.91l-41.76,0l16.76,45.99l23.58,0l1.42,-45.99z" fill="#2a5e00" fill-rule="evenodd" id="path15"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<rect x="20" y="10" width="10" height="80" rx="5" fill="#E61E25"/>
<rect x="50" y="10" width="10" height="80" rx="5" fill="#E61E25"/>
</svg>

Before

Width:  |  Height:  |  Size: 207 B

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Created with Inkscape (http://www.inkscape.org/) by Marsupilami -->
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="1024" height="357" viewBox="-1.98252 -1.98252 201.02104 70.04904" id="svg3349">
<defs id="defs3351"/>
<path d="m 0,0 11.76,0 4.455,31.962 0.12,0 L 20.789,0 32.55,0 23.402,42.417 9.147,42.417 0,0" id="path3131" style="fill:#1e1e1e;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
<path d="m 34.039,0 11.05,0 0,15.567 6.771,0 0,-15.567 11.05,0 0,42.417 -11.05,0 0,-17.465 -6.771,0 0,17.465 -11.05,0 0,-42.417" id="path3133" style="fill:#1e1e1e;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
<path d="m 64.395,0 11.757,0 4.457,31.962 0.121,0 L 85.185,0 96.944,0 87.797,42.417 73.54,42.417 64.395,0" id="path3135" style="fill:#1e1e1e;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
<path d="m 97.576,42.414 8.907,0 9.222,-42.41 -8.912,0 -9.217,42.41" id="path3137" style="fill:#f0ab00;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
<path d="m 111.026,42.424 8.908,-0.01 9.218,-42.41 -8.913,0 -9.213,42.42" id="path3139" style="fill:#f0ab00;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
<path d="m 124.564,42.414 8.906,0 9.217,-42.41 -8.906,0 -9.217,42.41" id="path3141" style="fill:#f0ab00;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
<path d="m 4.169,46.784 5.251,0 1.985,14.261 0.05,0 1.99,-14.261 5.247,0 -4.082,18.928 -6.363,0 -4.082,-18.928" id="path3143" style="fill:#1e1e1e;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
<path d="m 19.356,46.784 11.216,0 0,4.031 -6.282,0 0,3.234 5.882,0 0,3.87 -5.882,0 0,3.763 6.517,0 0,4.03 -11.451,0 0,-18.928" id="path3145" style="fill:#1e1e1e;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
<path d="m 54.93,52.247 0,-0.45 c 0,-1.117 -0.449,-2.043 -1.405,-2.043 -1.06,0 -1.538,0.823 -1.538,1.67 0,3.739 8.059,1.91 8.059,8.828 0,4.027 -2.357,5.832 -6.705,5.832 -4.082,0 -6.362,-1.404 -6.362,-5.331 l 0,-0.663 4.772,0 0,0.453 c 0,1.615 0.663,2.202 1.614,2.202 1.007,0 1.594,-0.798 1.594,-1.831 0,-3.739 -7.743,-1.88 -7.743,-8.586 0,-3.819 2.043,-5.913 6.205,-5.913 4.294,0 6.12,1.775 6.12,5.832 l -4.611,0" id="path3147" style="fill:#1e1e1e;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
<path d="m 61.476,65.712 4.932,0 0,-18.928 -4.932,0 0,18.928 z" id="path3149" style="fill:#1e1e1e;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
<path d="m 32.477,46.784 7.714,0 c 3.766,0 5.195,2.124 5.195,5.039 0,2.516 -0.979,4.16 -3.232,4.506 2.385,0.265 3.103,1.776 3.103,4.294 l 0,1.616 c 0,0.981 0,2.251 0.237,2.626 0.132,0.209 0.237,0.422 0.558,0.582 l 0,0.265 -5.25,0 C 40.325,64.705 40.325,62.9 40.325,62.109 l 0,-1.275 c 0,-2.147 -0.423,-2.704 -1.619,-2.704 l -1.296,0 0,7.582 -4.933,0 0,-18.928 z m 4.933,8.008 0.98,0 c 1.405,0 2.066,-0.9 2.066,-2.252 0,-1.541 -0.609,-2.202 -2.094,-2.202 l -0.952,0 0,4.454" id="path3151" style="fill:#1e1e1e;fill-opacity:1;fill-rule:evenodd;stroke:none"/>
<path d="m 75.975,52.54 c 0,-2.147 -0.396,-2.786 -1.35,-2.786 -1.513,0 -1.67,1.381 -1.67,6.494 0,5.117 0.157,6.497 1.67,6.497 1.22,0 1.485,-1.063 1.485,-4.64 l 4.771,0 0,1.405 c 0,5.3 -3.101,6.574 -6.256,6.574 -5.54,0 -6.76,-2.784 -6.76,-9.836 0,-7.236 1.642,-9.833 6.76,-9.833 4.451,0 6.12,2.334 6.12,5.992 l 0,1.19 -4.77,0 0,-1.057" id="path3153" style="fill:#1e1e1e;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
<path d="m 82.524,46.784 4.928,0 0,6.948 3.02,0 0,-6.948 4.932,0 0,18.928 -4.932,0 0,-7.793 -3.02,0 0,7.793 -4.928,0 0,-18.928" id="path3155" style="fill:#1e1e1e;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
<path d="m 97.606,46.784 11.21,0 0,4.031 -6.282,0 0,3.234 5.886,0 0,3.87 -5.886,0 0,3.763 6.522,0 0,4.03 -11.45,0 0,-18.928" id="path3157" style="fill:#1e1e1e;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
<path d="m 130.526,46.784 0,13.655 c 0,1.824 0.559,2.306 1.485,2.306 0.928,0 1.485,-0.482 1.485,-2.306 l 0,-13.655 4.929,0 0,12.408 c 0,5.298 -2.28,6.892 -6.414,6.892 -4.135,0 -6.412,-1.594 -6.412,-6.892 l 0,-12.408 4.927,0" id="path3159" style="fill:#1e1e1e;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
<path d="m 140.415,46.784 5.51,0 3.185,11.665 0.05,0 0,-11.665 4.614,0 0,18.928 -5.407,0 -3.288,-11.689 -0.05,0 0,11.689 -4.613,0 0,-18.928" id="path3161" style="fill:#1e1e1e;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
<path d="m 110.726,46.784 7.716,0 c 3.76,0 5.192,2.124 5.192,5.039 0,2.516 -0.979,4.16 -3.234,4.506 2.383,0.265 3.101,1.776 3.101,4.294 l 0,1.616 c 0,0.981 0,2.251 0.238,2.626 0.131,0.209 0.24,0.422 0.558,0.582 l 0,0.265 -5.251,0 c -0.477,-1.007 -0.477,-2.812 -0.477,-3.603 l 0,-1.275 c 0,-2.147 -0.422,-2.704 -1.612,-2.704 l -1.301,0 0,7.582 -4.93,0 0,-18.928 z m 4.93,8.008 0.979,0 c 1.404,0 2.07,-0.9 2.07,-2.252 0,-1.541 -0.61,-2.202 -2.095,-2.202 l -0.954,0 0,4.454" id="path3163" style="fill:#1e1e1e;fill-opacity:1;fill-rule:evenodd;stroke:none"/>
<path d="m 162.334,55.428 6.361,0 0,10.284 -3.34,0 -0.113,-1.669 -0.05,0 c -0.662,1.617 -2.412,2.041 -4.082,2.041 -5.01,0 -5.459,-3.58 -5.459,-9.836 0,-6.336 1.22,-9.833 7.047,-9.833 3.502,0 5.993,1.775 5.993,6.36 l -4.771,0 c 0,-0.952 -0.07,-1.695 -0.266,-2.198 -0.185,-0.53 -0.554,-0.823 -1.139,-0.823 -1.612,0 -1.774,1.381 -1.774,6.494 0,5.117 0.161,6.497 1.67,6.497 1.034,0 1.639,-0.666 1.669,-3.978 l -1.75,0 0,-3.339" id="path3165" style="fill:#1e1e1e;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
<path d="m 170.577,46.784 11.213,0 0,4.031 -6.28,0 0,3.234 5.885,0 0,3.87 -5.885,0 0,3.763 6.519,0 0,4.03 -11.452,0 0,-18.928" id="path3167" style="fill:#1e1e1e;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
<path d="m 183.697,46.784 5.514,0 3.18,11.665 0.05,0 0,-11.665 4.615,0 0,18.928 -5.408,0 -3.284,-11.689 -0.05,0 0,11.689 -4.614,0 0,-18.928" id="path3169" style="fill:#1e1e1e;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
</svg>
<!-- version: 20110311, original size: 197.056 66.084, border: 3% -->

Before

Width:  |  Height:  |  Size: 5.9 KiB

View File

@@ -39,8 +39,6 @@ PODS:
- DKPhotoGallery/Resource (0.0.19):
- SDWebImage
- SwiftyGif
- ente_qr (0.0.1):
- Flutter
- file_picker (0.0.1):
- DKImagePickerController/PhotoGallery
- Flutter
@@ -128,8 +126,6 @@ PODS:
- sqlite3/perf-threadsafe
- sqlite3/rtree
- SwiftyGif (5.4.5)
- ua_client_hints (1.4.1):
- Flutter
- url_launcher_ios (0.0.1):
- Flutter
@@ -138,7 +134,6 @@ DEPENDENCIES:
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
- cupertino_http (from `.symlinks/plugins/cupertino_http/darwin`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- ente_qr (from `.symlinks/plugins/ente_qr/ios`)
- file_picker (from `.symlinks/plugins/file_picker/ios`)
- file_saver (from `.symlinks/plugins/file_saver/ios`)
- fk_user_agent (from `.symlinks/plugins/fk_user_agent/ios`)
@@ -163,7 +158,6 @@ DEPENDENCIES:
- sodium_libs (from `.symlinks/plugins/sodium_libs/ios`)
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/darwin`)
- ua_client_hints (from `.symlinks/plugins/ua_client_hints/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
SPEC REPOS:
@@ -186,8 +180,6 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/cupertino_http/darwin"
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
ente_qr:
:path: ".symlinks/plugins/ente_qr/ios"
file_picker:
:path: ".symlinks/plugins/file_picker/ios"
file_saver:
@@ -236,8 +228,6 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/sqflite_darwin/darwin"
sqlite3_flutter_libs:
:path: ".symlinks/plugins/sqlite3_flutter_libs/darwin"
ua_client_hints:
:path: ".symlinks/plugins/ua_client_hints/ios"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
@@ -248,7 +238,6 @@ SPEC CHECKSUMS:
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
ente_qr: f39434aa69ea0e71047b49316365b2737f8a20aa
file_picker: b159e0c068aef54932bb15dc9fd1571818edaf49
file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808
fk_user_agent: 1f47ec39291e8372b1d692b50084b0d54103c545
@@ -279,7 +268,6 @@ SPEC CHECKSUMS:
sqlite3: 3e82a2daae39ba3b41ae6ee84a130494585460fc
sqlite3_flutter_libs: 2c48c4ee7217fd653251975e43412250d5bcbbe2
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
ua_client_hints: aeabd123262c087f0ce151ef96fa3ab77bfc8b38
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
PODFILE CHECKSUM: 78f002751f1a8f65042b8da97902ba4124271c5a

View File

@@ -111,7 +111,6 @@
"importAegisGuide": "Použijte možnost \"Export the vault\" v nastavení aplikace Aegis.",
"import2FasGuide": "Použijte možnost \"Settings->Backup -Export\" v 2FA.\n\nPokud je Vaše záloha šifrovaná, budete muset zadat heslo pro její odemčení",
"importLastpassGuide": "V nastavení aplikace Lastpass Authenticator vyberte možnost \"Transfer accounts\" a poté \"Export accounts to file\". Vygenerovaný soubor JSON následně nahrajte sem.",
"importProtonAuthGuide": "K exportu kódů použijte možnost „Exportovat“ v nastavení aplikace Proton Authenticator.",
"exportCodes": "Exportovat kódy",
"importLabel": "Importovat",
"importInstruction": "Vyberte, prosím, soubor obsahující seznam Vašich kódů v následujícím formátu",
@@ -125,7 +124,6 @@
"authToChangeYourEmail": "Pro změnu svého e-mailu se, prosím, ověřte",
"authToChangeYourPassword": "Pro změnu svého hesla se, prosím, ověřte",
"authToViewSecrets": "Pro zobrazení svých tajných údajů se musíte ověřit",
"authToInitiateSignIn": "Proveďte ověření a přihlaste se k zálohování.",
"ok": "Ok",
"cancel": "Zrušit",
"yes": "Ano",
@@ -173,7 +171,6 @@
"invalidQRCode": "Neplatný QR kód",
"noRecoveryKeyTitle": "Nemáte obnovovací klíč?",
"enterEmailHint": "Zadejte svou e-mailovou adresu",
"enterNewEmailHint": "Zadejte svou novou e-mailovou adresu",
"invalidEmailTitle": "Neplatná e-mailová adresa",
"invalidEmailMessage": "Prosím, zadejte platnou e-mailovou adresu.",
"deleteAccount": "Odstranit účet",
@@ -512,19 +509,6 @@
"supportEnte": "Podpořte <bold-green>ente</bold-green>",
"giveUsAStarOnGithub": "Dejte nám hvězdu na Githubu",
"free5GB": "5GB zdarma na <bold-green>ente</bold-green> Fotky",
"loginWithAuthAccount": "Přihlaste se pomocí svého účtu Auth",
"freeStorageOffer": "10% sleva na <bold-green>ente</bold-green> fotky",
"freeStorageOfferDescription": "Použijte kód \"AUTH\" pro získání 10% slevy na první rok",
"advanced": "Pokročilé",
"algorithm": "Algoritmus",
"type": "Typ",
"period": "Období",
"digits": "Digitální",
"importFromGallery": "Importovat z galerie",
"errorCouldNotReadImage": "Nelze přečíst vybraný obrazový soubor.",
"errorInvalidQRCode": "Neplatný QR kód",
"errorInvalidQRCodeBody": "Naskenovaný QR kód není platným účtem 2FA.",
"errorNoQRCode": "Nenalezen žádný QR kód",
"errorGenericTitle": "Došlo k chybě",
"errorGenericBody": "Při importu došlo k neočekávané chybě."
"freeStorageOfferDescription": "Použijte kód \"AUTH\" pro získání 10% slevy na první rok"
}

View File

@@ -111,7 +111,6 @@
"importAegisGuide": "Verwenden Sie die Option \"Tresor exportieren\" in den Einstellungen von Aegis.\n\nFalls Ihr Tresor verschlüsselt ist, müssen Sie das Passwort für den Tresor eingeben, um ihn zu entschlüsseln.",
"import2FasGuide": "Verwenden Sie unter \"Einstellungen → Backup\" die Option \"Exportieren\" in 2FAS.\n\nFalls Ihr Backup verschlüsselt ist, müssen Sie das Passwort eingeben, um das Backup zu entschlüsseln.",
"importLastpassGuide": "Verwenden Sie die Option \"Konten übertragen → Konten in Datei exportieren\" in den Lastpass Authenticator Einstellungen. \nImportieren Sie anschließend die heruntergeladene JSON-Datei.",
"importProtonAuthGuide": "Verwenden Sie die Option \"Exportieren\" in den Proton Authenticator Settings um Ihre Codes zu exportieren.",
"exportCodes": "Codes exportieren",
"importLabel": "Importieren",
"importInstruction": "Bitte wählen Sie eine Datei die Codes in folgendem Format beinhaltet",
@@ -520,12 +519,5 @@
"algorithm": "Algorithmus",
"type": "Typ",
"period": "Periode",
"digits": "Ziffern",
"importFromGallery": "Aus Galerie importieren",
"errorCouldNotReadImage": "Die ausgewählte Bild-Datei konnte nicht verarbeitet werden.",
"errorInvalidQRCode": "Ungültiger QR-Code",
"errorInvalidQRCodeBody": "Der gescannte QR-Code ist kein gültiges 2FA-Konto.",
"errorNoQRCode": "Kein QR-Code gefunden",
"errorGenericTitle": "Ein Fehler ist aufgetreten",
"errorGenericBody": "Beim Importieren ist ein unerwarteter Fehler aufgetreten."
"digits": "Ziffern"
}

View File

@@ -111,7 +111,6 @@
"importAegisGuide": "Use the \"Export the vault\" option in Aegis's Settings.\n\nIf your vault is encrypted, you will need to enter vault password to decrypt the vault.",
"import2FasGuide": "Use the \"Settings->Backup -Export\" option in 2FAS.\n\nIf your backup is encrypted, you will need to enter the password to decrypt the backup",
"importLastpassGuide": "Use the \"Transfer accounts\" option within Lastpass Authenticator Settings and press \"Export accounts to file\". Import the JSON downloaded.",
"importProtonAuthGuide": "Use the \"Export\" option in Proton Authenticator Settings to export your codes.",
"exportCodes": "Export codes",
"importLabel": "Import",
"importInstruction": "Please select a file that contains a list of your codes in the following format",
@@ -520,12 +519,5 @@
"algorithm": "Algorithm",
"type": "Type",
"period": "Period",
"digits": "Digits",
"importFromGallery": "Import from gallery",
"errorCouldNotReadImage": "Could not read the selected image file.",
"errorInvalidQRCode": "Invalid QR Code",
"errorInvalidQRCodeBody": "The scanned QR code is not a valid 2FA account.",
"errorNoQRCode": "No QR code found",
"errorGenericTitle": "An Error Occurred",
"errorGenericBody": "An unexpected error occurred while importing."
"digits": "Digits"
}

View File

@@ -111,7 +111,6 @@
"importAegisGuide": "Utilisez l'option \"Exporter le coffre-fort\" dans les paramètres d'Aegis.\n\nSi votre coffre-fort est crypté, vous devrez saisir le mot de passe du coffre-fort pour déchiffrer le coffre-fort.",
"import2FasGuide": "Utilisez l'option \"Paramètres->Sauvegarde -Export\" dans 2FAS.\n\nSi votre sauvegarde est chiffrée, vous devrez entrer le mot de passe pour déchiffrer la sauvegarde",
"importLastpassGuide": "Utilisez l'option \"Transférer des comptes\" dans les paramètres de l'authentificateur Lastpass et appuyez sur \"Exporter des comptes vers un fichier\". Importez le JSON téléchargé.",
"importProtonAuthGuide": "Utilisez l'option \"Export\" dans les paramètres de Proton Authenticator pour exporter vos codes.",
"exportCodes": "Exporter les codes",
"importLabel": "Importer",
"importInstruction": "Veuillez sélectionner un fichier qui contient une liste de vos codes dans le format suivant",
@@ -520,12 +519,5 @@
"algorithm": "Algorithme",
"type": "Type",
"period": "Période",
"digits": "Chiffres",
"importFromGallery": "Importer depuis la galerie",
"errorCouldNotReadImage": "Impossible de lire le fichier sélectionné.",
"errorInvalidQRCode": "QR Code invalide",
"errorInvalidQRCodeBody": "Le code QR scanné n'est pas un compte 2FA valide.",
"errorNoQRCode": "Aucun code QR trouvé",
"errorGenericTitle": "Une erreur s'est produite",
"errorGenericBody": "Une erreur inattendue est survenue lors de l'importation."
"digits": "Chiffres"
}

View File

@@ -111,7 +111,6 @@
"importAegisGuide": "Naudokite „Aegis“ nustatymuose esančią parinktį Eksportuoti slėptuvę.\n\nJei jūsų saugykla užšifruota, turėsite įvesti saugyklos slaptažodį, kad iššifruotumėte saugyklą.",
"import2FasGuide": "Naudokite programoje 2FAS esančią parinktį „Settings->2FAS Backup->Export to file“.\n\nJei atsarginė kopija užšifruota, turėsite įvesti slaptažodį, kad iššifruotumėte atsarginę kopiją.",
"importLastpassGuide": "Naudokite „Lastpass Authenticator“ nustatymuose esančią parinktį „Transfer accounts“ (perkelti paskyras) ir paspauskite „Export accounts to file“ (eksportuoti paskyras į failą). Importuokite atsisiųstą JSON failą.",
"importProtonAuthGuide": "Naudokite „Proton Authenticator“ nustatymuose esančią parinktį „Export“ (eksportuoti), kad eksportuotumėte savo kodus.",
"exportCodes": "Eksportuoti kodus",
"importLabel": "Importuoti",
"importInstruction": "Pasirinkite failą, kuriame yra tokio formato jūsų kodų sąrašas",
@@ -520,12 +519,5 @@
"algorithm": "Algoritmas",
"type": "Tipas",
"period": "Laikotarpis",
"digits": "Skaitmenys",
"importFromGallery": "Importuoti iš galerijos",
"errorCouldNotReadImage": "Nepavyko perskaityti pasirinkto vaizdo failo.",
"errorInvalidQRCode": "Netinkamas QR kodas",
"errorInvalidQRCodeBody": "Nuskenuotas QR kodas nėra tinkama 2FA paskyra.",
"errorNoQRCode": "QR kodas nerastas.",
"errorGenericTitle": "Įvyko klaida",
"errorGenericBody": "Importuojant įvyko netikėta klaida."
"digits": "Skaitmenys"
}

View File

@@ -111,7 +111,6 @@
"importAegisGuide": "Użyj opcji \"Eksportuj sejf\" w ustawieniach Aegis.\n\nJeśli twój sejf jest zaszyfrowany, musisz wprowadzić hasło sejfu, aby odszyfrować sejf.",
"import2FasGuide": "Użyj opcji \"Ustawienia->Kopia Zapasowa-Eksport\" w 2FAS.\n\nJeśli twoja kopia zapasowa jest zaszyfrowana, musisz wprowadzić hasło, aby odszyfrować kopię zapasową",
"importLastpassGuide": "Użyj opcji \"Przenieś konta\" w Ustawieniach Lastpass Authenticator i naciśnij \"Eksportuj konta do pliku\". Zaimportuj pobrany plik JSON.",
"importProtonAuthGuide": "Użyj opcji „Eksportuj” w ustawieniach Proton Authenticator, aby wyeksportować kody.",
"exportCodes": "Eksportuj kody",
"importLabel": "Importuj",
"importInstruction": "Wybierz plik, który zawiera listę twoich kodów w następującym formacie",
@@ -520,12 +519,5 @@
"algorithm": "Algorytm",
"type": "Rodzaj",
"period": "Okres",
"digits": "Cyfry",
"importFromGallery": "Importuj z galerii",
"errorCouldNotReadImage": "Nie można odczytać wybranego pliku obrazu.",
"errorInvalidQRCode": "Nieprawidłowy kod QR",
"errorInvalidQRCodeBody": "Zeskanowany kod QR nie wskazuje na prawidłowe konto 2FA.",
"errorNoQRCode": "Nie znaleziono kodu QR",
"errorGenericTitle": "Wystąpił błąd",
"errorGenericBody": "Podczas importowania wystąpił nieoczekiwany błąd."
"digits": "Cyfry"
}

View File

@@ -18,7 +18,7 @@
"incorrectDetails": "Felaktiga uppgifter",
"pleaseVerifyDetails": "Kontrollera dina detaljer och försök igen",
"codeIssuerHint": "Utfärdare",
"codeSecretKeyHint": "Hemlig nyckel",
"codeSecretKeyHint": "Secret Key",
"secret": "Säkerhetsnyckel",
"all": "Alla",
"notes": "Anteckningar",
@@ -33,7 +33,7 @@
}
}
},
"codeAccountHint": "Konto (du@domain.com)",
"codeAccountHint": "Konto (du@domän.com)",
"codeTagHint": "Tagg",
"accountKeyType": "Typ av nyckel",
"sessionExpired": "Sessionen har gått ut",
@@ -68,7 +68,7 @@
"reportABug": "Rapportera en bugg",
"crashAndErrorReporting": "Krasch och felrapportering",
"reportBug": "Rapportera bugg",
"emailUsMessage": "Skicka e-post till {email}",
"emailUsMessage": "Skicka e-mail till {email}",
"@emailUsMessage": {
"placeholders": {
"email": {
@@ -79,7 +79,7 @@
"contactSupport": "Kontakta support",
"rateUsOnStore": "Betygsätt på {storeName}",
"blog": "Blogg",
"merchandise": "Produkter",
"merchandise": "Merchandise",
"verifyPassword": "Bekräfta lösenord",
"pleaseWait": "Vänligen vänta...",
"generatingEncryptionKeysTitle": "Skapar krypteringsnycklar...",
@@ -104,14 +104,13 @@
"importFromApp": "Importera koder från {appName}",
"importGoogleAuthGuide": "Exportera dina konton från Google Authenticator till en QR-kod med alternativet \"Överföra konton\". Använd sedan en annan enhet och skanna QR-koden.\n\nTips: Du kan använda din bärbara dators webbkamera för att ta en bild av QR-koden.",
"importSelectJsonFile": "Välj JSON-fil",
"importSelectAppExport": "Välj {appName} exporteringsfil",
"importSelectAppExport": "Välj {appName} exportfil",
"importEnteEncGuide": "Välj den krypterade JSON-filen som exporteras från Ente",
"importRaivoGuide": "Använd alternativet \"Exportera OTPs till zip-arkiv\" i Raivos inställningar.\n\nExtrahera zip-filen och importera JSON-filen.",
"importBitwardenGuide": "Använd alternativet \"Exportera valv\" inom Bitwarden Tools och importera den okrypterade JSON-filen.",
"importAegisGuide": "Använd alternativet \"Exportera valvet\" i Aegis inställningar.\n\nOm ditt valv är krypterat måste du ange valvlösenordet för att dekryptera valvet.",
"import2FasGuide": "Använd alternativet \"Inställningar->Säkerhetskopiera -Exportera\" i 2FAS.\n\nOm din säkerhetskopia är krypterad måste du ange lösenordet för att dekryptera säkerhetskopian.",
"importLastpassGuide": "Använd alternativet \"Överför konton\" i LastPass Authenticators inställningar och tryck på \"Exportera konton till fil\". Importera JSON-filen som laddas ner.",
"importProtonAuthGuide": "Använd alternativet \"Exportera\" i Proton Authenticator-inställningarna för att exportera koder.",
"exportCodes": "Exportera koder",
"importLabel": "Importera",
"importInstruction": "Vänligen välj en fil som innehåller en lista över dina koder i följande format",
@@ -120,11 +119,11 @@
"emailVerificationToggle": "E-postverifiering",
"emailVerificationEnableWarning": "För att undvika att bli låst från ditt konto, se till att spara en kopia av din e-post 2FA utanför Ente Auth innan du aktiverar e-postverifiering.",
"authToChangeEmailVerificationSetting": "Autentisera för att ändra din e-postadress",
"authenticateGeneric": "Vänligen autentisera",
"authenticateGeneric": "Var god autentisera",
"authToViewYourRecoveryKey": "Autentisera för att visa din återställningsnyckel",
"authToChangeYourEmail": "Autentisera för att ändra din e-postadress",
"authToChangeYourPassword": "Autentisera för att ändra ditt lösenord",
"authToViewSecrets": "Vänligen autentisera för att visa din återställningsnyckel",
"authToViewSecrets": "Autentisera för att visa din återställningsnyckel",
"authToInitiateSignIn": "Vänligen autentisera för att initiera inloggning för säkerhetskopiering.",
"ok": "OK",
"cancel": "Avbryt",
@@ -148,7 +147,7 @@
"leaveFamily": "Lämna familjen",
"leaveFamilyMessage": "Är du säker på att du vill lämna familjeplanen?",
"inFamilyPlanMessage": "Du är på en familjeplan!",
"hintForMobile": "Tryck länge på en kod för att redigera eller ta bort.",
"hintForMobile": "Håll i på en kod för att redigera eller ta bort.",
"hintForDesktop": "Högerklicka på en kod för att redigera eller ta bort.",
"scan": "Skanna",
"scanACode": "Skanna kod",
@@ -192,7 +191,7 @@
"oopsSomethingWentWrong": "Hoppsan! Något gick fel.",
"selectLanguage": "Välj språk",
"language": "Språk",
"social": "Socialt",
"social": "Social",
"security": "Säkerhet",
"lockscreen": "Låsskärm",
"authToChangeLockscreenSetting": "Vänligen autentisera för att ändra låsskärms inställningar",
@@ -201,7 +200,7 @@
"authToViewYourActiveSessions": "Autentisera för att visa dina aktiva sessioner",
"searchHint": "Sök...",
"search": "Sök",
"sorryUnableToGenCode": "Tyvärr, kunde inte generera en kod för {issuerName}",
"sorryUnableToGenCode": "Tyvärr, det gick inte att generera en kod för {issuerName}",
"noResult": "Inga resultat",
"addCode": "Lägg till kod",
"scanAQrCode": "Skanna en QR-kod",
@@ -216,7 +215,7 @@
"error": "Fel",
"recoveryKeyCopiedToClipboard": "Återställningsnyckel kopierad till urklipp",
"recoveryKeyOnForgotPassword": "Om du glömmer ditt lösenord är det enda sättet du kan återställa dina data med denna nyckel.",
"recoveryKeySaveDescription": "Vi lagrar inte och har därför inte åtkomst till denna nyckel, vänligen spara denna 24 ordsnyckeln på en säker plats.",
"recoveryKeySaveDescription": "Vi lagrar inte och har därför inte åtkomst till denna nyckel, vänligen spara denna 24 ords nyckel på en säker plats.",
"doThisLater": "Gör detta senare",
"saveKey": "Spara nyckel",
"save": "Spara",
@@ -255,7 +254,7 @@
"insecureDevice": "Osäker enhet",
"sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Tyvärr, kunde vi inte generera säkra nycklar på den här enheten.\n\nvänligen registrera dig från en annan enhet.",
"howItWorks": "Så här fungerar det",
"ackPasswordLostWarning": "Jag förstår att om jag förlorar mitt lösenord kan jag förlora mina data eftersom min data är <underline>totalsträckskrypterad</underline>.",
"ackPasswordLostWarning": "Jag förstår att om jag förlorar mitt lösenord kan jag förlora mina data eftersom min data är <underline>end-to-end-krypterad</underline>.",
"loginTerms": "Jag samtycker till <u-terms>användarvillkoren</u-terms> och <u-policy>integritetspolicyn</u-policy>",
"logInLabel": "Logga in",
"logout": "Logga ut",
@@ -279,7 +278,7 @@
"recoveryKeyVerifyReason": "Din återställningsnyckel är det enda sättet att återställa dina foton om du glömmer ditt lösenord. Du hittar din återställningsnyckel i Inställningar > Säkerhet.\n\nAnge din återställningsnyckel här för att verifiera att du har sparat den ordentligt.",
"confirmYourRecoveryKey": "Bekräfta din återställningsnyckel",
"confirm": "Bekräfta",
"emailYourLogs": "E-posta dina loggar",
"emailYourLogs": "Maila dina loggar",
"pleaseSendTheLogsTo": "Vänligen skicka loggarna till \n{toEmail}",
"copyEmailAddress": "Kopiera e-postadress",
"exportLogs": "Exportera loggar",
@@ -298,7 +297,7 @@
"criticalUpdateAvailable": "Kritisk uppdatering tillgänglig",
"updateAvailable": "Uppdatering tillgänglig",
"update": "Uppdatera",
"checking": "Kontrollerar...",
"checking": "Kontrollerar ...",
"youAreOnTheLatestVersion": "Du är på den senaste versionen",
"warning": "Varning",
"exportWarningDesc": "Den exporterade filen innehåller känslig information. Förvara den på ett säkert sätt.",
@@ -307,7 +306,7 @@
"description": "Text for the button to confirm the user understands the warning"
},
"authToExportCodes": "Autentisera för att exportera dina koder",
"importSuccessTitle": "Hurra!",
"importSuccessTitle": "Jippi!",
"importSuccessDesc": "Du har importerat {count} koder!",
"@importSuccessDesc": {
"placeholders": {
@@ -325,7 +324,7 @@
"checkInboxAndSpamFolder": "Vänligen kontrollera din inkorg (och skräppost) för att slutföra verifieringen",
"tapToEnterCode": "Tryck för att ange kod",
"resendEmail": "Skicka e-post igen",
"weHaveSendEmailTo": "Vi har skickat ett e-postmeddelande till <green>{email}</green>",
"weHaveSendEmailTo": "Vi har skickat ett mail till <green>{email}</green>",
"@weHaveSendEmailTo": {
"description": "Text to indicate that we have sent a mail to the user",
"placeholders": {
@@ -363,7 +362,7 @@
"selectExportFormat": "Välj exportformat",
"exportDialogDesc": "Krypterad export skyddas av ett lösenord som du väljer.",
"encrypted": "Krypterad",
"plainText": "Oformaterad text",
"plainText": "Enkel text",
"passwordToEncryptExport": "Lösenord för att kryptera export",
"export": "Exportera",
"useOffline": "Använd utan säkerhetskopior",
@@ -375,14 +374,14 @@
"compactMode": "Kompakt läge",
"shouldHideCode": "Dölj koder",
"doubleTapToViewHiddenCode": "Du kan dubbeltrycka på en post för att visa koden",
"focusOnSearchBar": "Fokusera på sök vid uppstart av app",
"focusOnSearchBar": "Fokusera på sök vid appstart",
"confirmUpdatingkey": "Är du säker på att du vill uppdatera den hemliga nyckeln?",
"minimizeAppOnCopy": "Minimera appen vid kopiering",
"editCodeAuthMessage": "Autentisera för att redigera kod",
"deleteCodeAuthMessage": "Autentisera för att radera kod",
"showQRAuthMessage": "Autentisera för att visa QR-kod",
"confirmAccountDeleteTitle": "Bekräfta radering av kontot",
"confirmAccountDeleteMessage": "Detta konto är kopplat till andra Ente applikationer, om du använder någon.\n\nDina uppladdade data, över alla Ente applikationer, kommer att schemaläggas för radering och ditt konto kommer att raderas permanent.",
"confirmAccountDeleteMessage": "Detta konto är kopplat till andra Ente apps, om du använder någon.\n\nDina uppladdade data, över alla Ente appar, kommer att schemaläggas för radering och ditt konto kommer att raderas permanent.",
"androidBiometricHint": "Verifiera identitet",
"@androidBiometricHint": {
"description": "Hint message advising the user how to authenticate with biometrics. It is used on Android side. Maximum 60 characters."
@@ -391,7 +390,7 @@
"@androidBiometricNotRecognized": {
"description": "Message to let the user know that authentication was failed. It is used on Android side. Maximum 60 characters."
},
"androidBiometricSuccess": "Lyckades",
"androidBiometricSuccess": "Slutförd",
"@androidBiometricSuccess": {
"description": "Message to let the user know that authentication was successful. It is used on Android side. Maximum 60 characters."
},
@@ -442,7 +441,7 @@
"signOutOtherDevices": "Logga ut andra enheter",
"doNotSignOut": "Logga inte ut",
"hearUsWhereTitle": "Hur hörde du talas om Ente? (valfritt)",
"hearUsExplanation": "Vi spårar inte installationer. Det skulle hjälpa oss om du berättade hur du hittade oss!",
"hearUsExplanation": "Vi spårar inte appinstallationer, Det skulle hjälpa oss om du berättade var du hittade oss!",
"recoveryKeySaved": "Återställningsnyckel sparad i nedladdningsmappen!",
"waitingForBrowserRequest": "Väntar på webbläsarbegäran...",
"waitingForVerification": "Väntar på verifiering...",
@@ -489,8 +488,6 @@
"hideContent": "Dölj innehåll",
"hideContentDescriptionAndroid": "Döljer appinnehåll i app-växlaren och inaktiverar skärmdumpar",
"hideContentDescriptioniOS": "Döljer appinnehåll i app-växlaren",
"autoLockFeatureDescription": "Tid efter vilken appen låses efter att ha satts i bakgrunden",
"appLockDescription": "Välj mellan enhetens förvalda låsskärm och en anpassad låsskärm med en PIN-kod eller lösenord.",
"pinLock": "Pinkodslås",
"enterPin": "Ange PIN-kod",
"setNewPin": "Ställ in ny PIN-kod",
@@ -501,31 +498,9 @@
"appLockOfflineModeWarning": "Du har valt att fortsätta utan säkerhetskopior. Om du glömmer ditt applås, kommer du att bli utelåst från att komma åt dina data.",
"duplicateCodes": "Dubblettkoder",
"noDuplicates": "✨ Inga dubbletter",
"youveNoDuplicateCodesThatCanBeCleared": "Du har inga dubbla koder som kan rensas",
"deduplicateCodes": "Deduplicera koder",
"deselectAll": "Avmarkera alla",
"selectAll": "Markera alla",
"deleteDuplicates": "Radera dubbletter",
"plainHTML": "Ren HTML",
"tellUsWhatYouThink": "Berätta vad du tycker",
"dropReviewiOS": "Skriv en recension på App Store",
"dropReviewAndroid": "Skriv en recension på Play Store",
"supportEnte": "Stöd <bold-green>ente</bold-green>",
"giveUsAStarOnGithub": "Ge oss en stjärna på Github",
"free5GB": "5 GB gratis på <bold-green>ente</bold-green> Foton",
"loginWithAuthAccount": "Logga in med ditt Auth-konto",
"freeStorageOffer": "10% rabatt på <bold-green>ente</bold-green> foton",
"freeStorageOfferDescription": "Använd koden \"AUTH\" för att få 10% rabatt första året",
"advanced": "Avancerad",
"algorithm": "Algoritm",
"type": "Typ",
"period": "Tidsperiod",
"digits": "Siffror",
"importFromGallery": "Importera från galleri",
"errorCouldNotReadImage": "Kunde inte läsa den valda bildfilen.",
"errorInvalidQRCode": "Ogiltig QR-kod",
"errorInvalidQRCodeBody": "Den skannade QR-koden är inte ett giltigt 2FA konto.",
"errorNoQRCode": "Ingen QR-kod hittades",
"errorGenericTitle": "Ett fel inträffade",
"errorGenericBody": "Ett oväntat fel inträffade vid import."
"plainHTML": "Ren HTML"
}

View File

@@ -6,7 +6,7 @@
"@counterAppBarTitle": {
"description": "Text shown in the AppBar of the Counter Page"
},
"onBoardingBody": "妥善保管您的双重认证代码",
"onBoardingBody": "妥善保管您的两步验证码",
"onBoardingGetStarted": "开始",
"setupFirstAccount": "设置您的第一个账户",
"importScanQrCode": "扫描二维码",
@@ -111,14 +111,13 @@
"importAegisGuide": "使用 Aegis 设置中的“导出密码库”选项。\n\n如果您的密码库已加密则需要输入密码库密码才能解密密码库。",
"import2FasGuide": "使用 2FAS 中的“设置 -> 备份 -> 导出”选项。\n\n如果您的备份已加密则需要输入密码来解密备份",
"importLastpassGuide": "使用 Lastpass Authenticator 设置中的“转移账户”选项,然后按“将账户导出到文件”。导入下载的 JSON。",
"importProtonAuthGuide": "使用 Proton Authenticator 设置中的“导出”选项导出您的代码。",
"exportCodes": "导出代码",
"importLabel": "导入",
"importInstruction": "请选择一个包含以下格式的代码列表的文件",
"importCodeDelimiterInfo": "代码可以用逗号或换行符分隔",
"selectFile": "选择文件",
"emailVerificationToggle": "电子邮件验证",
"emailVerificationEnableWarning": "为避免被锁在您的账户之外,请在启用电子邮件验证之前确保在 Ente Auth 之外存储电子邮件双重认证的副本。",
"emailVerificationEnableWarning": "为避免被锁在您的账户之外,请在启用电子邮件验证之前确保在 Ente Auth 之外存储电子邮件两步验证的副本。",
"authToChangeEmailVerificationSetting": "请进行身份验证以更改电子邮件验证",
"authenticateGeneric": "请验证",
"authToViewYourRecoveryKey": "请验证以查看您的恢复密钥",
@@ -156,7 +155,7 @@
"verifyEmail": "验证电子邮件",
"enterCodeHint": "从你的身份验证器应用中\n输入6位数字代码",
"lostDeviceTitle": "丢失了设备吗?",
"twoFactorAuthTitle": "双重认证",
"twoFactorAuthTitle": "两步验证",
"passkeyAuthTitle": "通行密钥验证",
"verifyPasskey": "验证通行密钥",
"loginWithTOTP": "使用 TOTP 登录",
@@ -520,12 +519,5 @@
"algorithm": "算法",
"type": "类型",
"period": "周期",
"digits": "数字",
"importFromGallery": "从图库导入",
"errorCouldNotReadImage": "无法读取所选图片文件。",
"errorInvalidQRCode": "二维码无效",
"errorInvalidQRCodeBody": "扫描的二维码不是有效的双重认证账户。",
"errorNoQRCode": "未找到二维码",
"errorGenericTitle": "出错了",
"errorGenericBody": "导入时发生意外错误。"
"digits": "数字"
}

View File

@@ -39,9 +39,7 @@ import 'package:ente_auth/utils/totp_util.dart';
import 'package:ente_events/event_bus.dart';
import 'package:ente_lock_screen/lock_screen_settings.dart';
import 'package:ente_lock_screen/ui/app_lock.dart';
import 'package:ente_qr/ente_qr.dart';
import 'package:ente_ui/pages/base_home_page.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@@ -50,7 +48,7 @@ import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:logging/logging.dart';
import 'package:move_to_background/move_to_background.dart';
class HomePage extends BaseHomePage {
class HomePage extends BaseHomePage {
const HomePage({super.key});
@override
@@ -64,7 +62,6 @@ class _HomePageState extends State<HomePage> {
);
bool _hasLoaded = false;
bool _isSettingsOpen = false;
bool _isImportingFromGallery = false;
final Logger _logger = Logger("HomePage");
final scaffoldKey = GlobalKey<ScaffoldState>();
@@ -291,63 +288,6 @@ class _HomePageState extends State<HomePage> {
}
}
Future<void> _importFromGalleryNative() async {
final l10n = AppLocalizations.of(context);
if (_isImportingFromGallery) {
return;
}
_isImportingFromGallery = true;
try {
final FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.image,
);
if (result == null || result.files.single.path == null) {
return;
}
final String imagePath = result.files.single.path!;
final enteQr = EnteQr();
final QrScanResult qrResult = await enteQr.scanQrFromImage(imagePath);
if (qrResult.success && qrResult.content != null) {
try {
final newCode = Code.fromOTPAuthUrl(qrResult.content!);
await CodeStore.instance.addCode(newCode, shouldSync: false);
// Focus the new code by searching
if ((_allCodes?.where((e) => !e.hasError).length ?? 0) > 2) {
_focusNewCode(newCode);
}
} catch (e) {
_logger.severe('Error adding code from QR scan', e);
await showErrorDialog(
context,
l10n.errorInvalidQRCode,
l10n.errorInvalidQRCodeBody,
);
}
} else {
_logger.warning('QR scan failed: ${qrResult.error}');
await showErrorDialog(
context,
l10n.errorNoQRCode,
qrResult.error ?? l10n.errorNoQRCode,
);
}
} catch (e) {
await showErrorDialog(
context,
l10n.errorGenericTitle,
l10n.errorGenericBody,
);
} finally {
_isImportingFromGallery = false;
}
}
Future<void> _redirectToScannerPage() async {
final Code? code = await Navigator.of(context).push(
MaterialPageRoute(
@@ -805,14 +745,6 @@ class _HomePageState extends State<HomePage> {
labelWidget: SpeedDialLabelWidget(context.l10n.enterDetailsManually),
onTap: _redirectToManualEntryPage,
),
if (PlatformUtil.isMobile())
SpeedDialChild(
child: const Icon(Icons.image),
backgroundColor: Theme.of(context).colorScheme.fabBackgroundColor,
foregroundColor: Theme.of(context).colorScheme.fabForegroundColor,
labelWidget: SpeedDialLabelWidget(context.l10n.importFromGallery),
onTap: _importFromGalleryNative,
),
],
);
}

View File

@@ -4,7 +4,6 @@ import 'package:ente_auth/ui/settings/data/import/encrypted_ente_import.dart';
import 'package:ente_auth/ui/settings/data/import/google_auth_import.dart';
import 'package:ente_auth/ui/settings/data/import/lastpass_import.dart';
import 'package:ente_auth/ui/settings/data/import/plain_text_import.dart';
import 'package:ente_auth/ui/settings/data/import/proton_import.dart';
import 'package:ente_auth/ui/settings/data/import/raivo_plain_text_import.dart';
import 'package:ente_auth/ui/settings/data/import/two_fas_import.dart';
import 'package:ente_auth/ui/settings/data/import_page.dart';
@@ -44,9 +43,6 @@ class ImportService {
case ImportType.lastpass:
await showLastpassImportInstruction(context);
break;
case ImportType.proton:
await showProtonImportInstruction(context);
break;
}
}
}

View File

@@ -1,171 +0,0 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/models/code.dart';
import 'package:ente_auth/services/authenticator_service.dart';
import 'package:ente_auth/store/code_store.dart';
import 'package:ente_auth/ui/common/progress_dialog.dart';
import 'package:ente_auth/ui/components/buttons/button_widget.dart';
import 'package:ente_auth/ui/components/dialog_widget.dart';
import 'package:ente_auth/ui/components/models/button_type.dart';
import 'package:ente_auth/ui/settings/data/import/import_success.dart';
import 'package:ente_auth/utils/dialog_util.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
Future<void> showProtonImportInstruction(BuildContext context) async {
final l10n = context.l10n;
final result = await showDialogWidget(
context: context,
title: l10n.importFromApp("Proton Authenticator"),
body: l10n.importProtonAuthGuide,
buttons: [
ButtonWidget(
buttonType: ButtonType.primary,
labelText: l10n.importSelectJsonFile,
isInAlert: true,
buttonSize: ButtonSize.large,
buttonAction: ButtonAction.first,
),
ButtonWidget(
buttonType: ButtonType.secondary,
labelText: context.l10n.cancel,
buttonSize: ButtonSize.large,
isInAlert: true,
buttonAction: ButtonAction.second,
),
],
);
if (result?.action != null && result!.action != ButtonAction.cancel) {
if (result.action == ButtonAction.first) {
await _pickProtonJsonFile(context);
}
}
}
Future<void> _pickProtonJsonFile(BuildContext context) async {
final l10n = context.l10n;
FilePickerResult? result = await FilePicker.platform
.pickFiles(dialogTitle: l10n.importSelectJsonFile);
if (result == null) {
return;
}
final ProgressDialog progressDialog =
createProgressDialog(context, l10n.pleaseWait);
await progressDialog.show();
try {
String path = result.files.single.path!;
int? count = await _processProtonExportFile(context, path, progressDialog);
await progressDialog.hide();
if (count != null) {
await importSuccessDialog(context, count);
}
} catch (e, s) {
Logger('ProtonImport')
.severe('exception while processing proton import', e, s);
await progressDialog.hide();
await showErrorDialog(
context,
context.l10n.sorry,
"${context.l10n.importFailureDescNew}\n Error: ${e.toString()}",
);
}
}
Future<int?> _processProtonExportFile(
BuildContext context,
String path,
final ProgressDialog dialog,
) async {
File file = File(path);
final jsonString = await file.readAsString();
final decodedJson = jsonDecode(jsonString);
// Validate that this is a Proton export
if (decodedJson['version'] == null || decodedJson['entries'] == null) {
await dialog.hide();
await showErrorDialog(
context,
'Invalid Proton export',
'The selected file is not a valid Proton Authenticator export.',
);
return null;
}
final parsedCodes = <Code>[];
final entries = decodedJson['entries'] as List;
for (var entry in entries) {
try {
final content = entry['content'];
if (content == null) {
continue; // Skip entries without content
}
final entryType = content['entry_type'] as String?;
if (entryType != 'Totp' && entryType != 'Steam') {
// log warning
Logger('ProtonImport').warning('Unsupported entry type: $entryType');
continue; // Skip non-TOTP and non-Steam entries
}
Code code;
if (entryType == 'Steam') {
// Handle Steam entries with steam:// format
final steamUri = content['uri'] as String?;
if (steamUri == null || !steamUri.startsWith('steam://')) {
continue; // Skip invalid Steam URIs
}
final secret = steamUri.split('steam://')[1];
final name = content['name'] as String? ?? '';
code = Code.fromAccountAndSecret(
Type.steam,
'', // Steam doesn't typically have separate account
name, // Use name as issuer
secret,
null,
Code.steamDigits,
);
} else {
// Handle TOTP entries with otpauth:// format
final otpUri = content['uri'] as String?;
if (otpUri == null || !otpUri.startsWith('otpauth://')) {
continue; // Skip invalid OTP URIs
}
// Create code from OTP auth URL
code = Code.fromOTPAuthUrl(otpUri);
}
// Add note if present
final note = entry['note'] as String?;
if (note != null && note.isNotEmpty) {
code = code.copyWith(
display: code.display.copyWith(note: note),
);
}
parsedCodes.add(code);
} catch (e, s) {
Logger('ProtonImport').warning('Failed to parse entry', e, s);
// Continue processing other entries
}
}
// Add all parsed codes to the store
for (final code in parsedCodes) {
await CodeStore.instance.addCode(code, shouldSync: false);
}
// Trigger sync
unawaited(AuthenticatorService.instance.onlineSync());
return parsedCodes.length;
}

View File

@@ -17,7 +17,6 @@ enum ImportType {
twoFas,
bitwarden,
lastpass,
proton,
}
class ImportCodePage extends StatelessWidget {
@@ -30,7 +29,6 @@ class ImportCodePage extends StatelessWidget {
ImportType.aegis,
ImportType.bitwarden,
ImportType.googleAuthenticator,
ImportType.proton,
ImportType.ravio,
ImportType.lastpass,
];
@@ -53,8 +51,6 @@ class ImportCodePage extends StatelessWidget {
return 'Bitwarden';
case ImportType.lastpass:
return 'LastPass Authenticator';
case ImportType.proton:
return 'Proton Authenticator';
}
}

View File

@@ -1,33 +0,0 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "761747bfc538b5af34aa0d3fac380f1bc331ec49"
channel: "stable"
project_type: plugin
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: android
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: ios
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'

View File

@@ -1,8 +0,0 @@
## 0.0.1
* Initial release of ente_qr plugin
* Support for scanning QR codes from image files
* Android implementation using ZXing library
* iOS implementation using Core Image framework
* Comprehensive error handling
* Example app demonstrating usage with file picker

View File

@@ -1,170 +0,0 @@
# ente_qr
A Flutter plugin for scanning QR codes from image files. This plugin provides a simple interface to scan QR codes from images on both Android and iOS platforms.
## Features
- Scan QR codes from image files
- Support for Android (using ZXing library)
- Support for iOS (using AVFoundation/Core Image)
- Returns structured results with error handling
- Works with images from file picker or camera
## Platform Support
| Platform | Support |
|----------|---------|
| Android | ✅ |
| iOS | ✅ |
| Web | ❌ |
| macOS | ❌ |
| Windows | ❌ |
| Linux | ❌ |
## Installation
Add this to your package's `pubspec.yaml` file:
```yaml
dependencies:
ente_qr:
path: path/to/ente_qr
```
## Usage
### Basic Usage
```dart
import 'package:ente_qr/ente_qr.dart';
final qr = EnteQr();
// Scan QR code from an image file
final result = await qr.scanQrFromImage('/path/to/image.jpg');
if (result.success) {
print('QR Code content: ${result.content}');
} else {
print('Error: ${result.error}');
}
```
### Complete Example with File Picker
```dart
import 'package:flutter/material.dart';
import 'package:ente_qr/ente_qr.dart';
import 'package:file_picker/file_picker.dart';
class QrScannerPage extends StatefulWidget {
@override
_QrScannerPageState createState() => _QrScannerPageState();
}
class _QrScannerPageState extends State<QrScannerPage> {
final _enteQr = EnteQr();
String _result = 'No QR code scanned';
Future<void> _scanQrFromImage() async {
// Pick an image file
FilePickerResult? fileResult = await FilePicker.platform.pickFiles(
type: FileType.image,
allowMultiple: false,
);
if (fileResult != null && fileResult.files.single.path != null) {
final imagePath = fileResult.files.single.path!;
// Scan QR code from the selected image
final qrResult = await _enteQr.scanQrFromImage(imagePath);
setState(() {
if (qrResult.success) {
_result = 'QR Code: ${qrResult.content}';
} else {
_result = 'Error: ${qrResult.error}';
}
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('QR Scanner')),
body: Column(
children: [
ElevatedButton(
onPressed: _scanQrFromImage,
child: Text('Pick Image and Scan QR'),
),
Text(_result),
],
),
);
}
}
```
## API Reference
### EnteQr
The main class for QR code scanning operations.
#### Methods
##### `scanQrFromImage(String imagePath)`
Scans a QR code from an image file.
**Parameters:**
- `imagePath` (String): The file path to the image containing the QR code
**Returns:**
- `Future<QrScanResult>`: A result object containing either the QR code content or an error
### QrScanResult
The result object returned by QR scanning operations.
**Properties:**
- `content` (String?): The QR code content if successful, null otherwise
- `error` (String?): Error message if scanning failed, null otherwise
- `success` (bool): Whether the scanning operation was successful
**Factory Constructors:**
- `QrScanResult.success(String content)`: Creates a successful result
- `QrScanResult.error(String error)`: Creates an error result
## Implementation Details
### Android
The Android implementation uses the ZXing library (com.google.zxing) for QR code detection:
- `com.journeyapps:zxing-android-embedded:4.3.0`
- `com.google.zxing:core:3.5.1`
### iOS
The iOS implementation uses Core Image framework's built-in QR code detection capabilities via `CIDetector`.
## Error Handling
The plugin provides comprehensive error handling for common scenarios:
- File not found
- Invalid image format
- No QR code found in image
- Platform-specific errors
- Unexpected errors
All errors are returned as part of the `QrScanResult` object with descriptive error messages.
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## License
This project is licensed under the same license as the Ente project.

View File

@@ -1 +0,0 @@
include: ../../analysis_options.yaml

View File

@@ -1,65 +0,0 @@
group 'io.ente.auth.ente_qr'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.7.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.3.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
rootProject.allprojects {
repositories {
google()
mavenCentral()
}
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 33
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
test.java.srcDirs += 'src/test/kotlin'
}
defaultConfig {
minSdkVersion 16
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
implementation 'com.google.zxing:core:3.5.1'
}
testOptions {
unitTests.all {
useJUnitPlatform()
testLogging {
events "passed", "skipped", "failed", "standardOut", "standardError"
outputs.upToDateWhen {false}
showStandardStreams = true
}
}
}
}

View File

@@ -1 +0,0 @@
rootProject.name = 'ente_qr'

View File

@@ -1,3 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.ente.auth.ente_qr">
</manifest>

View File

@@ -1,138 +0,0 @@
package io.ente.auth.ente_qr
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import androidx.annotation.NonNull
import com.google.zxing.BarcodeFormat
import com.google.zxing.BinaryBitmap
import com.google.zxing.DecodeHintType
import com.google.zxing.MultiFormatReader
import com.google.zxing.NotFoundException
import com.google.zxing.RGBLuminanceSource
import com.google.zxing.Result as ZXingResult
import com.google.zxing.common.HybridBinarizer
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import java.io.File
import java.util.*
/** EnteQrPlugin */
class EnteQrPlugin: FlutterPlugin, MethodCallHandler {
/// The MethodChannel that will the communication between Flutter and native Android
///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
/// when the Flutter Engine is detached from the Activity
private lateinit var channel : MethodChannel
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "ente_qr")
channel.setMethodCallHandler(this)
}
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
when (call.method) {
"getPlatformVersion" -> {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
}
"scanQrFromImage" -> {
val imagePath = call.argument<String>("imagePath")
if (imagePath == null) {
result.success(mapOf(
"success" to false,
"error" to "Image path is required"
))
return
}
try {
val qrResult = scanQrCode(imagePath)
result.success(qrResult)
} catch (e: Exception) {
result.success(mapOf(
"success" to false,
"error" to "Error scanning QR code: ${e.message}"
))
}
}
else -> {
result.notImplemented()
}
}
}
private fun scanQrCode(imagePath: String): Map<String, Any> {
try {
val file = File(imagePath)
if (!file.exists()) {
return mapOf(
"success" to false,
"error" to "Image file not found: $imagePath"
)
}
var bitmap = BitmapFactory.decodeFile(imagePath)
if (bitmap == null) {
return mapOf(
"success" to false,
"error" to "Unable to decode image file"
)
}
// Try multiple times with different image sizes like Aegis does
for (i in 0..2) {
if (i != 0) {
// Resize bitmap for subsequent attempts
val newWidth = bitmap.width / (i * 2)
val newHeight = bitmap.height / (i * 2)
if (newWidth > 0 && newHeight > 0) {
bitmap = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true)
}
}
try {
val width = bitmap.width
val height = bitmap.height
val pixels = IntArray(width * height)
bitmap.getPixels(pixels, 0, width, 0, 0, width, height)
val source = RGBLuminanceSource(width, height, pixels)
val binaryBitmap = BinaryBitmap(HybridBinarizer(source))
val reader = MultiFormatReader()
val hints = HashMap<DecodeHintType, Any>()
hints[DecodeHintType.POSSIBLE_FORMATS] = listOf(BarcodeFormat.QR_CODE)
hints[DecodeHintType.TRY_HARDER] = true
hints[DecodeHintType.ALSO_INVERTED] = true
reader.setHints(hints)
val qrResult: ZXingResult = reader.decode(binaryBitmap)
return mapOf(
"success" to true,
"content" to qrResult.text
)
} catch (e: NotFoundException) {
// Continue to next iteration
continue
}
}
return mapOf(
"success" to false,
"error" to "No QR code found in image"
)
} catch (e: Exception) {
return mapOf(
"success" to false,
"error" to "Error scanning QR code: ${e.message}"
)
}
}
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}
}

View File

@@ -1,77 +0,0 @@
import Flutter
import UIKit
import AVFoundation
public class EnteQrPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "ente_qr", binaryMessenger: registrar.messenger())
let instance = EnteQrPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "getPlatformVersion":
result("iOS " + UIDevice.current.systemVersion)
case "scanQrFromImage":
guard let args = call.arguments as? [String: Any],
let imagePath = args["imagePath"] as? String else {
result([
"success": false,
"error": "Image path is required"
])
return
}
scanQrCode(from: imagePath, result: result)
default:
result(FlutterMethodNotImplemented)
}
}
private func scanQrCode(from imagePath: String, result: @escaping FlutterResult) {
guard let image = UIImage(contentsOfFile: imagePath) else {
result([
"success": false,
"error": "Unable to load image from path: \(imagePath)"
])
return
}
guard let cgImage = image.cgImage else {
result([
"success": false,
"error": "Unable to get CGImage from UIImage"
])
return
}
let detector = CIDetector(ofType: CIDetectorTypeQRCode,
context: nil,
options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])
guard let qrDetector = detector else {
result([
"success": false,
"error": "Unable to create QR code detector"
])
return
}
let ciImage = CIImage(cgImage: cgImage)
let features = qrDetector.features(in: ciImage)
if let qrFeature = features.first as? CIQRCodeFeature,
let messageString = qrFeature.messageString {
result([
"success": true,
"content": messageString
])
} else {
result([
"success": false,
"error": "No QR code found in image"
])
}
}
}

View File

@@ -1,23 +0,0 @@
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
# Run `pod lib lint ente_qr.podspec` to validate before publishing.
#
Pod::Spec.new do |s|
s.name = 'ente_qr'
s.version = '0.0.1'
s.summary = 'A QR code reader plugin for Ente.'
s.description = <<-DESC
A QR code reader plugin for Ente.
DESC
s.homepage = 'https://ente.io'
s.license = { :file => '../LICENSE' }
s.author = { 'Ente' => 'team@ente.io' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.dependency 'Flutter'
s.platform = :ios, '9.0'
# Flutter.framework does not contain a i386 slice.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
s.swift_version = '5.0'
end

View File

@@ -1,30 +0,0 @@
import 'package:ente_qr/ente_qr_platform_interface.dart';
export 'ente_qr_platform_interface.dart' show QrScanResult;
class EnteQr {
Future<String?> getPlatformVersion() {
return EnteQrPlatform.instance.getPlatformVersion();
}
/// Scans a QR code from an image file at the given path.
///
/// [imagePath] - The file path to the image containing the QR code
///
/// Returns a [QrScanResult] containing either the QR code content on success
/// or an error message on failure.
///
/// Example:
/// ```dart
/// final qr = EnteQr();
/// final result = await qr.scanQrFromImage('/path/to/image.jpg');
/// if (result.success) {
/// print('QR Code content: ${result.content}');
/// } else {
/// print('Error: ${result.error}');
/// }
/// ```
Future<QrScanResult> scanQrFromImage(String imagePath) {
return EnteQrPlatform.instance.scanQrFromImage(imagePath);
}
}

View File

@@ -1,52 +0,0 @@
import 'package:ente_qr/ente_qr_platform_interface.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
/// An implementation of [EnteQrPlatform] that uses method channels.
class MethodChannelEnteQr extends EnteQrPlatform {
/// The method channel used to interact with the native platform.
@visibleForTesting
final methodChannel = const MethodChannel('ente_qr');
@override
Future<String?> getPlatformVersion() async {
final version =
await methodChannel.invokeMethod<String>('getPlatformVersion');
return version;
}
@override
Future<QrScanResult> scanQrFromImage(String imagePath) async {
try {
final dynamic result = await methodChannel.invokeMethod(
'scanQrFromImage',
{'imagePath': imagePath},
);
if (result == null) {
return QrScanResult.error('Failed to scan QR code');
}
// Convert to Map<String, dynamic> safely
final Map<String, dynamic> resultMap =
Map<String, dynamic>.from(result as Map);
final bool success = resultMap['success'] as bool? ?? false;
if (success) {
final String? content = resultMap['content'] as String?;
if (content != null && content.isNotEmpty) {
return QrScanResult.success(content);
} else {
return QrScanResult.error('No QR code found in image');
}
} else {
final String? error = resultMap['error'] as String?;
return QrScanResult.error(error ?? 'Unknown error occurred');
}
} on PlatformException catch (e) {
return QrScanResult.error('Platform error: ${e.message}');
} catch (e) {
return QrScanResult.error('Unexpected error: $e');
}
}
}

View File

@@ -1,61 +0,0 @@
import 'package:ente_qr/ente_qr_method_channel.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
/// The result of QR code scanning
class QrScanResult {
final String? content;
final String? error;
final bool success;
const QrScanResult({
this.content,
this.error,
required this.success,
});
factory QrScanResult.success(String content) {
return QrScanResult(
content: content,
success: true,
);
}
factory QrScanResult.error(String error) {
return QrScanResult(
error: error,
success: false,
);
}
}
abstract class EnteQrPlatform extends PlatformInterface {
/// Constructs a EnteQrPlatform.
EnteQrPlatform() : super(token: _token);
static final Object _token = Object();
static EnteQrPlatform _instance = MethodChannelEnteQr();
/// The default instance of [EnteQrPlatform] to use.
///
/// Defaults to [MethodChannelEnteQr].
static EnteQrPlatform get instance => _instance;
/// Platform-specific implementations should set this with their own
/// platform-specific class that extends [EnteQrPlatform] when
/// they register themselves.
static set instance(EnteQrPlatform instance) {
PlatformInterface.verifyToken(instance, _token);
_instance = instance;
}
Future<String?> getPlatformVersion() {
throw UnimplementedError('platformVersion() has not been implemented.');
}
/// Scans a QR code from an image file at the given path.
/// Returns the QR code content as a string if successful, null otherwise.
Future<QrScanResult> scanQrFromImage(String imagePath) {
throw UnimplementedError('scanQrFromImage() has not been implemented.');
}
}

View File

@@ -1,213 +0,0 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
async:
dependency: transitive
description:
name: async
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
url: "https://pub.dev"
source: hosted
version: "2.13.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
characters:
dependency: transitive
description:
name: characters
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
url: "https://pub.dev"
source: hosted
version: "1.4.0"
clock:
dependency: transitive
description:
name: clock
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
url: "https://pub.dev"
source: hosted
version: "1.1.2"
collection:
dependency: transitive
description:
name: collection
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
url: "https://pub.dev"
source: hosted
version: "1.19.1"
fake_async:
dependency: transitive
description:
name: fake_async
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
url: "https://pub.dev"
source: hosted
version: "1.3.3"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1"
url: "https://pub.dev"
source: hosted
version: "3.0.2"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
url: "https://pub.dev"
source: hosted
version: "10.0.9"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
url: "https://pub.dev"
source: hosted
version: "3.0.9"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
lints:
dependency: transitive
description:
name: lints
sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
url: "https://pub.dev"
source: hosted
version: "3.0.0"
matcher:
dependency: transitive
description:
name: matcher
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
url: "https://pub.dev"
source: hosted
version: "0.12.17"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.dev"
source: hosted
version: "0.11.1"
meta:
dependency: transitive
description:
name: meta
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
url: "https://pub.dev"
source: hosted
version: "1.16.0"
path:
dependency: transitive
description:
name: path
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
url: "https://pub.dev"
source: hosted
version: "1.9.1"
plugin_platform_interface:
dependency: "direct main"
description:
name: plugin_platform_interface
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
url: "https://pub.dev"
source: hosted
version: "2.1.8"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
source_span:
dependency: transitive
description:
name: source_span
sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
url: "https://pub.dev"
source: hosted
version: "1.10.1"
stack_trace:
dependency: transitive
description:
name: stack_trace
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
url: "https://pub.dev"
source: hosted
version: "1.12.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
url: "https://pub.dev"
source: hosted
version: "1.4.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
url: "https://pub.dev"
source: hosted
version: "1.2.2"
test_api:
dependency: transitive
description:
name: test_api
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
url: "https://pub.dev"
source: hosted
version: "0.7.4"
vector_math:
dependency: transitive
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
url: "https://pub.dev"
source: hosted
version: "15.0.0"
sdks:
dart: ">=3.7.0-0 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54"

View File

@@ -1,29 +0,0 @@
name: ente_qr
description: "A QR code reader plugin for Ente."
version: 0.0.1
homepage: https://ente.io
environment:
sdk: '>=3.4.3 <4.0.0'
flutter: '>=3.3.0'
dependencies:
flutter:
sdk: flutter
plugin_platform_interface: ^2.0.2
dev_dependencies:
flutter_lints: ^3.0.0
flutter_test:
sdk: flutter
# The following section is specific to Flutter packages.
flutter:
# This section identifies this Flutter project as a plugin project.
plugin:
platforms:
android:
package: io.ente.auth.ente_qr
pluginClass: EnteQrPlugin
ios:
pluginClass: EnteQrPlugin

View File

@@ -1,32 +0,0 @@
import 'package:ente_qr/ente_qr.dart';
import 'package:ente_qr/ente_qr_method_channel.dart';
import 'package:ente_qr/ente_qr_platform_interface.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
class MockEnteQrPlatform
with MockPlatformInterfaceMixin
implements EnteQrPlatform {
@override
Future<String?> getPlatformVersion() => Future.value('42');
@override
Future<QrScanResult> scanQrFromImage(String imagePath) =>
Future.value(QrScanResult.error('Mock implementation'));
}
void main() {
final EnteQrPlatform initialPlatform = EnteQrPlatform.instance;
test('$MethodChannelEnteQr is the default instance', () {
expect(initialPlatform, isInstanceOf<MethodChannelEnteQr>());
});
test('getPlatformVersion', () async {
final EnteQr enteQrPlugin = EnteQr();
final MockEnteQrPlatform fakePlatform = MockEnteQrPlatform();
EnteQrPlatform.instance = fakePlatform;
expect(await enteQrPlugin.getPlatformVersion(), '42');
});
}

View File

@@ -451,13 +451,6 @@ packages:
relative: true
source: path
version: "1.0.0"
ente_qr:
dependency: "direct main"
description:
path: "plugins/qr"
relative: true
source: path
version: "0.0.1"
ente_strings:
dependency: "direct main"
description:
@@ -473,7 +466,7 @@ packages:
source: path
version: "1.0.0"
ente_utils:
dependency: "direct overridden"
dependency: transitive
description:
path: "../../packages/utils"
relative: true
@@ -539,10 +532,10 @@ packages:
dependency: "direct main"
description:
name: file_picker
sha256: e7e16c9d15c36330b94ca0e2ad8cb61f93cd5282d0158c09805aed13b5452f22
sha256: ef9908739bdd9c476353d6adff72e88fd00c625f5b959ae23f7567bd5137db0a
url: "https://pub.dev"
source: hosted
version: "10.3.2"
version: "10.2.0"
file_saver:
dependency: "direct main"
description:
@@ -958,7 +951,7 @@ packages:
source: hosted
version: "0.1.0"
image:
dependency: "direct main"
dependency: transitive
description:
name: image
sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928"

View File

@@ -1,6 +1,6 @@
name: ente_auth
description: ente two-factor authenticator
version: 4.4.7+447
version: 4.4.6+446
publish_to: none
environment:
@@ -41,8 +41,6 @@ dependencies:
path: ../../packages/logging
ente_network:
path: ../../packages/network
ente_qr:
path: plugins/qr
ente_strings:
path: ../../packages/strings
ente_ui:
@@ -52,7 +50,7 @@ dependencies:
expansion_tile_card: ^3.0.0
ffi: ^2.1.0
figma_squircle: ^0.6.3
file_picker: ^10.3.2
file_picker: ^10.2.0
file_saver: ^0.3.1
fixnum: ^1.1.0
fk_user_agent: # no package updates on pub.dev
@@ -86,7 +84,6 @@ dependencies:
google_nav_bar: ^5.0.5 #supported
gradient_borders: ^1.0.0
http: ^1.1.0
image: ^4.5.4
intl: ^0.20.2
io: ^1.0.4
json_annotation: ^4.5.0

View File

@@ -1,22 +0,0 @@
# melos_managed_dependency_overrides: ente_accounts,ente_base,ente_configuration,ente_events,ente_lock_screen,ente_logging,ente_network,ente_strings,ente_ui,ente_utils
dependency_overrides:
ente_accounts:
path: ../../packages/accounts
ente_base:
path: ../../packages/base
ente_configuration:
path: ../../packages/configuration
ente_events:
path: ../../packages/events
ente_lock_screen:
path: ../../packages/lock_screen
ente_logging:
path: ../../packages/logging
ente_network:
path: ../../packages/network
ente_strings:
path: ../../packages/strings
ente_ui:
path: ../../packages/ui
ente_utils:
path: ../../packages/utils

View File

@@ -1,7 +1 @@
# Ente Locker
## TODOs
Refactor and merge
- [ ] Verify correctness for `PackageInfoUtil.getPackageName()` on Linux and Windows
- [ ] Update `file_url.dart` to download only via CF worker when necessary
# soon.

View File

@@ -1 +1,72 @@
include: ../../analysis_options.yaml
# For more linters, we can check https://dart-lang.github.io/linter/lints/index.html
# or https://pub.dev/packages/lint (Effective dart)
# use "flutter analyze ." or "dart analyze ." for running lint checks
include: package:flutter_lints/flutter.yaml
linter:
rules:
# Ref https://github.com/flutter/packages/blob/master/packages/flutter_lints/lib/flutter.yaml
# Ref https://dart-lang.github.io/linter/lints/
- avoid_print
- avoid_unnecessary_containers
- avoid_web_libraries_in_flutter
- no_logic_in_create_state
- prefer_const_constructors
- prefer_const_constructors_in_immutables
- prefer_const_declarations
- prefer_const_literals_to_create_immutables
- prefer_final_locals
- require_trailing_commas
- sized_box_for_whitespace
- use_full_hex_values_for_flutter_colors
- use_key_in_widget_constructors
- cancel_subscriptions
- avoid_empty_else
- exhaustive_cases
# just style suggestions
- sort_pub_dependencies
- use_rethrow_when_possible
- prefer_double_quotes
- directives_ordering
- always_use_package_imports
- sort_child_properties_last
- unawaited_futures
analyzer:
errors:
avoid_empty_else: error
exhaustive_cases: error
curly_braces_in_flow_control_structures: error
directives_ordering: error
require_trailing_commas: error
always_use_package_imports: warning
prefer_final_fields: error
unused_import: error
camel_case_types: error
prefer_is_empty: warning
use_rethrow_when_possible: info
unused_field: warning
use_key_in_widget_constructors: warning
sort_child_properties_last: warning
sort_pub_dependencies: warning
library_private_types_in_public_api: warning
constant_identifier_names: ignore
prefer_const_constructors: warning
prefer_const_declarations: warning
prefer_const_constructors_in_immutables: warning
prefer_final_locals: warning
unnecessary_const: error
cancel_subscriptions: error
unrelated_type_equality_checks: error
unnecessary_cast: info
unawaited_futures: warning # convert to warning after fixing existing issues
invalid_dependency: info
use_build_context_synchronously: ignore # experimental lint, requires many changes
prefer_interpolation_to_compose_strings: ignore # later too many warnings
prefer_double_quotes: ignore # too many warnings
avoid_renaming_method_parameters: ignore # incorrect warnings for `equals` overrides

View File

@@ -8,7 +8,7 @@
<application
android:label="Ente Locker"
android:name="${applicationName}"
android:icon="@mipmap/icon_blue">
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground>
<inset
android:drawable="@drawable/ic_launcher_foreground"
android:inset="16%" />
</foreground>
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#1071ff</color>
</resources>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 680 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

View File

@@ -75,9 +75,9 @@ PODS:
- FlutterMacOS
- privacy_screen (0.0.1):
- Flutter
- SDWebImage (5.21.1):
- SDWebImage/Core (= 5.21.1)
- SDWebImage/Core (5.21.1)
- SDWebImage (5.21.0):
- SDWebImage/Core (= 5.21.0)
- SDWebImage/Core (5.21.0)
- Sentry/HybridSDK (8.46.0)
- sentry_flutter (8.14.2):
- Flutter
@@ -209,7 +209,7 @@ SPEC CHECKSUMS:
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
privacy_screen: 1a131c052ceb3c3659934b003b0d397c2381a24e
SDWebImage: f29024626962457f3470184232766516dee8dfea
SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868
Sentry: da60d980b197a46db0b35ea12cb8f39af48d8854
sentry_flutter: 2df8b0aab7e4aba81261c230cbea31c82a62dd1b
share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f

View File

@@ -622,7 +622,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = IconBlue;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
@@ -929,7 +929,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = IconBlue;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
@@ -956,7 +956,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = IconBlue;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

View File

@@ -1 +0,0 @@
{"images":[{"size":"20x20","idiom":"iphone","filename":"IconBlue-20x20@2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"IconBlue-20x20@3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"IconBlue-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"iphone","filename":"IconBlue-29x29@2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"IconBlue-29x29@3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"IconBlue-40x40@2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"IconBlue-40x40@3x.png","scale":"3x"},{"size":"57x57","idiom":"iphone","filename":"IconBlue-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"IconBlue-57x57@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"IconBlue-60x60@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"IconBlue-60x60@3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"IconBlue-20x20@1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"IconBlue-20x20@2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"IconBlue-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"IconBlue-29x29@2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"IconBlue-40x40@1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"IconBlue-40x40@2x.png","scale":"2x"},{"size":"50x50","idiom":"ipad","filename":"IconBlue-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"IconBlue-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"IconBlue-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"IconBlue-72x72@2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"IconBlue-76x76@1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"IconBlue-76x76@2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"IconBlue-83.5x83.5@2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"IconBlue-1024x1024@1x.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Some files were not shown because too many files have changed in this diff Show More