Compare commits

..

3 Commits

Author SHA1 Message Date
Neeraj Gupta
4e3448d97e Add release 4.4.4 to appdata.xml 2025-08-09 00:49:25 +05:30
Neeraj Gupta
6ac99e6e97 Bump version code 2025-08-09 00:48:32 +05:30
Neeraj Gupta
b57b012840 Bump version 2025-08-09 00:24:48 +05:30
1490 changed files with 73294 additions and 133836 deletions

View File

@@ -5,7 +5,7 @@ on:
branches: [main]
paths:
# Run workflow when auth's intl_en.arb is changed
- "mobile/apps/auth/lib/l10n/arb/app_en.arb"
- "auth/lib/l10n/arb/app_en.arb"
# Or the workflow itself is changed
- ".github/workflows/auth-crowdin.yml"

View File

@@ -4,7 +4,7 @@ on:
workflow_dispatch: # Allow manually running the action
env:
FLUTTER_VERSION: "3.32.8"
FLUTTER_VERSION: "3.24.3"
permissions:
contents: write

View File

@@ -4,11 +4,11 @@ on:
# Run on every pull request (open or push to it) that changes auth/
pull_request:
paths:
- "mobile/apps/auth/**"
- "auth/**"
- ".github/workflows/auth-lint.yml"
env:
FLUTTER_VERSION: "3.32.8"
FLUTTER_VERSION: "3.24.3"
permissions:
contents: read

View File

@@ -29,7 +29,7 @@ on:
- "auth-v*"
env:
FLUTTER_VERSION: "3.32.8"
FLUTTER_VERSION: "3.24.3"
permissions:
contents: write

View File

@@ -1,179 +0,0 @@
name: "Internal release (photos)"
on:
schedule:
# Runs daily at 12:30 UTC (6:00 PM IST)
- cron: "30 12 * * *"
workflow_dispatch: # Allow manual trigger
env:
FLUTTER_VERSION: "3.32.8"
RUST_VERSION: "1.86.0"
permissions:
contents: read
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: 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:
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 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: //')
VERSION_NAME=$(echo $CURRENT_VERSION | cut -d'+' -f1)
CURRENT_BUILD=$(echo $CURRENT_VERSION | cut -d'+' -f2)
NEW_BUILD=$((CURRENT_BUILD + ${{ github.run_number }}))
NEW_VERSION="${VERSION_NAME}+${NEW_BUILD}"
sed -i "s/^version: .*/version: $NEW_VERSION/" pubspec.yaml
echo "Building with version ${NEW_VERSION}"
# Store version for later use
echo "NEW_VERSION=${NEW_VERSION}" >> $GITHUB_ENV
- name: Prepare and validate changelog for Play Store
run: |
mkdir -p whatsnew
CHANGELOG_FILE="scripts/store_changes.txt"
DISCORD_FILE="scripts/internal_changes.txt"
OUTPUT_FILE="whatsnew/whatsnew-en-US"
# Use provided changelog or fallback
if [ -f "$CHANGELOG_FILE" ]; then
head -c 500 "$CHANGELOG_FILE" > "$OUTPUT_FILE"
else
echo "Bug fixes and improvements" > "$OUTPUT_FILE"
fi
# Validate: file exists
if [ ! -s "$OUTPUT_FILE" ]; then
echo "❌ Changelog is empty."
exit 1
fi
# Validate: <= 500 chars
LENGTH=$(wc -m < "$OUTPUT_FILE")
if [ "$LENGTH" -gt 500 ]; then
echo "❌ Changelog exceeds 500 characters ($LENGTH)."
exit 1
fi
# Validate: no markdown or HTML
if grep -Eq '[\*\_\<\>\[\]\(\)]' "$OUTPUT_FILE"; then
echo "❌ Changelog contains markdown/HTML formatting."
exit 1
fi
echo "✅ Changelog valid:"
cat "$OUTPUT_FILE"
# Store changelog for Play Store (with escaped newlines)
CHANGELOG_PLAYSTORE=$(cat "$OUTPUT_FILE" | sed ':a;N;$!ba;s/\n/\\n/g' | sed 's/"/\\"/g')
echo "CHANGELOG=${CHANGELOG_PLAYSTORE}" >> $GITHUB_ENV
# Store changelog for Discord (with proper newlines)
CHANGELOG_DISCORD=$(cat "$DISCORD_FILE" | sed 's/"/\\"/g')
echo "CHANGELOG_DISCORD<<EOF" >> $GITHUB_ENV
echo "$CHANGELOG_DISCORD" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- 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
whatsNewDirectory: mobile/apps/photos/whatsnew
mappingFile: mobile/apps/photos/build/app/outputs/mapping/playstoreRelease/mapping.txt
- name: Notify Discord
uses: sarisia/actions-status-discord@v1
with:
webhook: ${{ secrets.DISCORD_INTERNAL_RELEASE_WEBHOOK }}
nodetail: true
title: "🏆 Daily release Photos v${{ env.NEW_VERSION }} (Branch: ${{ github.ref_name }})"
description: |
**Version:** ${{ env.NEW_VERSION }}
**Flutter:** ${{ env.FLUTTER_VERSION }}
**Commit:** [${{ github.sha }}](${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }})
**Download:** [Play Store](https://play.google.com/store/apps/details?id=io.ente.photos)
**Changes:**
${{ env.CHANGELOG_DISCORD }}
color: 0x00ff00

View File

@@ -0,0 +1,77 @@
name: "Internal release (photos)"
on:
workflow_dispatch: # Allow manually running the action
env:
FLUTTER_VERSION: "3.24.3"
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 available for Photos"
description: "[Download](https://play.google.com/store/apps/details?id=io.ente.photos)"
color: 0x00ff00

View File

@@ -0,0 +1,68 @@
name: "Internal release (photos)"
on:
workflow_dispatch: # Allow manually running the action
env:
FLUTTER_VERSION: "3.24.3"
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: 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

@@ -8,8 +8,7 @@ on:
- ".github/workflows/mobile-lint.yml"
env:
FLUTTER_VERSION: "3.32.8"
RUST_VERSION: "1.86.0"
FLUTTER_VERSION: "3.24.3"
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

@@ -9,7 +9,7 @@ on:
- "photos-v*"
env:
FLUTTER_VERSION: "3.32.8"
FLUTTER_VERSION: "3.24.3"
permissions:
contents: write
@@ -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

@@ -4,7 +4,7 @@ on:
workflow_dispatch: # Manual trigger only
env:
FLUTTER_VERSION: "3.32.8"
FLUTTER_VERSION: "3.24.3"
ANDROID_KEYSTORE_PATH: "keystore/ente_photos_key.jks"
jobs:

View File

@@ -54,18 +54,6 @@ jobs:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: pages deploy --project-name=ente --commit-dirty=true --branch=deploy/photos web/apps/photos/out
- name: Build custom-albums
run: yarn build:photos
env:
NEXT_PUBLIC_ENTE_ONLY_SERVE_ALBUMS_APP: 1
- name: Publish custom-albums
uses: cloudflare/wrangler-action@v3
with:
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: pages deploy --project-name=ente --commit-dirty=true --branch=deploy/custom-albums web/apps/photos/out
- name: Build accounts
run: yarn build:accounts

3
.gitmodules vendored
View File

@@ -9,6 +9,3 @@
[submodule "auth/assets/simple-icons"]
path = mobile/apps/auth/assets/simple-icons
url = https://github.com/simple-icons/simple-icons.git
[submodule "mobile/thirdparty/flutter"]
path = mobile/thirdparty/flutter
url = https://github.com/flutter/flutter.git

View File

@@ -48,11 +48,7 @@ See [docs/](docs/README.md) for how to edit these documents.
## Code contributions
If you'd like to contribute code, it is best to start small. Consider some well-scoped changes, say like adding more [custom icons to auth](mobile/apps/auth/docs/adding-icons.md), or fixing a specific bug. There is a (possibly outdated) list of tasks with the ["help wanted" or "good first issue"](<https://github.com/ente-io/ente/issues?q=state%3Aopen%20(label%3A%22good%20first%20issue%22%20OR%20label%3A%22help%20wanted%22%20)>) label too.
If you use any form of AI assistance, please include a co-author attribution in the commit for transparency.
In your PR, please include before / after screenshots, and clearly indicate the tests that you performed.
If you'd like to contribute code, it is best to start small. Consider some well-scoped changes, say like adding more [custom icons to auth](mobile/apps/auth/docs/adding-icons.md), or fixing a specific bug.
Code that changes the behaviour of the product might not get merged, at least not initially. The PR can serve as a discussion bed, but you might find it easier to just start a discussion instead, or post your perspective in the (likely) existing thread about the behaviour change or new feature you wish for.

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

@@ -2,11 +2,10 @@ package cmd
import (
"fmt"
"os"
"runtime"
"github.com/ente-io/cli/pkg"
"github.com/spf13/cobra/doc"
"os"
"runtime"
"github.com/spf13/viper"
@@ -21,6 +20,11 @@ var ctrl *pkg.ClICtrl
var rootCmd = &cobra.Command{
Use: "ente",
Short: "CLI tool for exporting your photos from ente.io",
// Uncomment the following line if your bare application
// has an action associated with it:
Run: func(cmd *cobra.Command, args []string) {
fmt.Sprintf("Hello World")
},
}
func GenerateDocs() error {

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

@@ -26,10 +26,6 @@ export const sidebar = [
text: "Collecting photos",
link: "/photos/features/collect",
},
{
text: "Custom domains",
link: "/photos/features/custom-domains/",
},
{
text: "Deduplicate",
link: "/photos/features/deduplicate",

View File

View File

@@ -35,4 +35,4 @@ be specific to your distro (e.g. `xdg-desktop-menu forceupdate`).
> [!NOTE]
>
> If you're using an AppImage and not seeing the icon, you'll need to
> [enable AppImage desktop integration](/photos/troubleshooting/desktop-install/#appimage-desktop-integration).
> [enable AppImage desktop integration](/photos/troubleshooting/desktop-install/#appimage-desktop-integration).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

View File

@@ -1,105 +0,0 @@
---
title: Custom domains
description: Use your own domain when sharing photos and videos stored in Ente Photos
---
# Custom domains
Custom domains allow you to serve your public links with your own personalized domain.
For example, if I have an Ente album and wish to share it with my friends, I can go to the album's sharing settings and create a public link. When I copy this link, it will of the form of
```
https://albums.ente.io/?t=...
```
The custom domains feature allows you to instead create a link that uses your own domain, say
```
https://pics.example.org/?t=...
```
You don't need to run any servers or manage any services, Ente will still host and serve your album for you, the only thing that changes is that you can serve your links using your personalized domain.
## Availability
The custom domains feature requires the ability to publicly share albums which for abuse prevention reasons can only be done by people with an active Ente subscription.
## Setup
The setup involves two steps:
1. Letting Ente know about the domain you wish to use for serving your public links
2. Updating your DNS settings to point your domain (or subdomain) to **my.ente.io**
For people who are comfortable with changing DNS settings on their domain provider, this entire process is very simple will take a minute. For people who are not comfortable with changing DNS, we will provide a more detailed breakdown below.
Let's dive in.
To make the process concrete, let's assume we're trying to use _pics.example.org_ as our custom domain. Note that there is no restriction to use a subdomain, a top level domain can be used as a custom domain too. That is, either of _example.org_ or _subdomain.example.org_ is fine, Ente will work with both.
### Step 1 - Link your domain
The first step is to let Ente know about the domain or subdomain you wish to use by linking it to your account.
> [!WARNING]
>
> Currently (Aug 2025) the ability to link a custom domain is only present in Ente's web app, [web.ente.io](https://web.ente.io). It will come to Ente mobile and desktop when their next versions get released.
Head over to Preferences > Custom domains, in the domain field enter "pics.example.org" (replace with your subdomain) and press "Save". That's it. The linking is done.
### Step 2 - Add DNS entry
The second step is to add a CNAME entry in your DNS provider that forwards requests for pics.example.org (replace with your subdomain) to **my.ente.io**.
Specifically, you need to add a `CNAME record` from the domain (or subdomain) of your choice to `my.ente.io`. You can leave the `TTL` at its default.
| Record Type | Name | Value | TTL |
| ----------- | :------------------------: | -----------: | -------------- |
| CNAME | Your subdomain, e.g `pics` | `my.ente.io` | Auto (default) |
The exact steps for doing this depend on the DNS provider that you're using.
> Your DNS provider usually is the service from which you bought your domain. The domain name seller will provide some sort of an admin panel where you can configure your DNS settings.
As concrete examples, here is how this step would look for Cloudflare:
![Adding a CNAME for custom domain in Cloudflare](cf.png)
Note that orange proxy option is off. And here is how it would look for Namecheap:
![Adding a CNAME for custom domain in Namecheap](nc.png)
> [!NOTE]
>
> The examples are using "pics" as the subdomain, but that's just an example, you can use anything you like (or use "@" if you'd like to use the root domain itself).
The time it takes for DNS records to update is dependent on your DNS provider. Usually the changes should start reflecting within a few minutes, and should almost always reflect within an hour.
Once the DNS changes have been applied, then you can take any public link to your shared albums, replace `albums.ente.io` with your choice (e.g. `pics.example.org`), and the link will still work.
You don't need to do this manually though, the apps will do it for you. More on this in the next section. But first, some troubleshooting tips.
### Troubleshooting
If your domain is not working, go through the following checklist.
- The CNAME should be from your domain to my.ente.io, not the other way around. That is, `pics.example.org => my.ente.io`.
- If you're using Cloudflare DNS, make sure that the "Orange" proxy status toggle is off, and the Proxy status is the "Grey" DNS only.
## Using
Using is trivial. When you go to an album's sharing options and copy the link to it, Ente will automatically copy the link that uses your configured domain.
> [!WARNING]
>
> Currently (Aug 2025) the ability to automatically substitute your custom domain is only present in Ente's web app, [web.ente.io](https://web.ente.io). It will come to Ente mobile and desktop when their next versions get released.
## Unsetting
To stop using your custom domain, we need to undo the two steps we did during setup.
1. Unlink your domain in Ente. This can be done just by going to Preferences > Custom Domains, clearing the value in the "Domain" input and pressing "Update".
2. Remove the CNAME record you added during setup in your DNS provider.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -112,4 +112,4 @@ ip addr add 10.10.10.1/24 dev dummy0
ip link set dummy0 up
```
Once the interface is up, Ente correctly detects that the system is online.
Once the interface is up, Ente correctly detects that the system is online.

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

@@ -63,20 +63,11 @@ It has no relation to Backblaze, Wasabi or Scaleway.
Each bucket's endpoint, region, key and secret should be configured accordingly
if using an external bucket.
If a bucket has SSL support enabled, set `s3.are_local_buckets` to `false`. Enable path-style URL by setting `s3.use_path_style_urls` to `true`.
::: note
You can configure this for individual buckets over defining top-level configuration if you are using the latest server image (August 2025)
:::
A sample configuration for `b2-eu-cen` is provided, which can be used for other 2 buckets as well:
A sample configuration for `b2-eu-cen` is provided, which can be used for other
2 buckets as well:
```yaml
b2-eu-cen:
are_local_buckets: true
use_path_style_urls: true
key: <key>
secret: <secret>
endpoint: localhost:3200

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

@@ -96,8 +96,8 @@ provide correct credentials for proper connectivity within Museum.
The `s3` section within `museum.yaml` is by default configured to use local
MinIO buckets when using `quickstart.sh` or Docker Compose.
If you wish to use an external S3 provider with SSL, you can edit the configuration with
your provider's credentials, and set `s3.are_local_buckets` to `false`. Additionally, you can configure this for specific buckets in the corresponding bucket sections in the Compose file.
If you wish to use an external S3 provider, you can edit the configuration with
your provider's credentials, and set `s3.are_local_buckets` to `false`.
If you are using default MinIO, it is accessible at port `3200`. Web Console can
be accessed by enabling port `3201` in the Compose file.
@@ -111,11 +111,11 @@ and [troubleshooting](/self-hosting/troubleshooting/uploads) sections.
| Variable | Description | Default |
| -------------------------------------- | -------------------------------------------- | ------- |
| `s3.b2-eu-cen` | Primary hot storage bucket configuration | |
| `s3.b2-eu-cen` | Primary hot storage S3 config | |
| `s3.wasabi-eu-central-2-v3.compliance` | Whether to disable compliance lock on delete | `true` |
| `s3.scw-eu-fr-v3` | Cold storage bucket configuration | |
| `s3.wasabi-eu-central-2-v3` | Secondary hot storage configuration | |
| `s3.are_local_buckets` | | `true` |
| `s3.scw-eu-fr-v3` | Optional secondary S3 config | |
| `s3.wasabi-eu-central-2-derived` | Derived data storage | |
| `s3.are_local_buckets` | Use local MinIO-compatible storage | `false` |
| `s3.use_path_style_urls` | Enable path-style URLs for MinIO | `false` |
### Encryption Keys
@@ -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

View File

@@ -1,15 +0,0 @@
{
email custom-domains@ente.io
on_demand_tls {
ask https://api.ente.io/custom-domain
}
}
https:// {
tls {
on_demand
}
reverse_proxy https://custom-albums.ente.io {
header_up Host {upstream_hostport}
}
}

View File

@@ -1,19 +0,0 @@
# Caddy
Caddy is used to terminate TLS and manage certificates for custom domains.
## Installation
```sh
sudo mkdir -p /root/caddy/conf
sudo mv Caddyfile /root/caddy/conf
sudo chown root:root /root/caddy/conf/Caddyfile
```
Rest of it works like our other systemd services.
If the Caddyfile changes, the running instance can be updated without restarts by using `sudo systemctl reload caddy`.
## Backups
The entire `/root/caddy` directory can be backed up and contains the everything needed to resurrect the same setup.

View File

@@ -1,17 +0,0 @@
[Unit]
Documentation=https://caddyserver.com/docs/running
Requires=docker.service
After=docker.service
[Service]
ExecStartPre=docker pull caddy
ExecStartPre=-docker stop caddy
ExecStartPre=-docker rm caddy
ExecStart=docker run --name caddy \
--cap-add NET_ADMIN \
-p 80:80 -p 443:443 -p 443:443/udp \
-v /root/caddy/conf:/etc/caddy \
-v /root/caddy/data:/data \
-v /root/caddy/config:/config \
caddy
ExecReload=docker exec -w /etc/caddy caddy caddy reload

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

@@ -1,3 +1,3 @@
{
"flutter": "3.32.8"
"flutter": "3.24.3"
}

View File

@@ -44,5 +44,4 @@ android/key.properties
dist/
# FVM Version Cache
.fvm/
lib/l10n/arb/*.dart
.fvm/

View File

@@ -44,7 +44,7 @@ or managing your secrets, please use our mobile or desktop app.
## 🧑‍💻 Build from source
1. [Install Flutter v3.32.8](https://flutter.dev/docs/get-started/install).
1. [Install Flutter](https://flutter.dev/docs/get-started/install)
2. Pull in all submodules with `git submodule update --init --recursive`

View File

@@ -30,13 +30,10 @@ if (keystorePropertiesFile.exists()) {
android {
namespace "io.ente.auth"
compileSdk 36
compileSdk 34
ndkVersion flutter.ndkVersion
compileOptions {
// Flag to enable support for the new language APIs
coreLibraryDesugaringEnabled true
// Sets Java compatibility to Java 8
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
@@ -59,8 +56,8 @@ android {
applicationId "io.ente.auth"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion 22
targetSdkVersion 35
minSdkVersion 21
targetSdkVersion 34
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -118,7 +115,4 @@ flutter {
source '../..'
}
dependencies {
// For AGP 7.4+
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
}
dependencies {}

View File

@@ -1,6 +0,0 @@
# Please add these rules to your existing keep rules in order to suppress warnings.
# This is generated automatically by the Android Gradle plugin.
-dontwarn com.google.errorprone.annotations.CanIgnoreReturnValue
-dontwarn com.google.errorprone.annotations.CheckReturnValue
-dontwarn com.google.errorprone.annotations.Immutable
-dontwarn com.google.errorprone.annotations.RestrictedApi

View File

@@ -6,19 +6,6 @@ allprojects {
}
rootProject.buildDir = '../build'
subprojects {
afterEvaluate { project ->
if (project.hasProperty('android')) {
project.android {
if (namespace == null) {
namespace project.group
}
}
}
}
}
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}

View File

@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip

View File

@@ -19,8 +19,8 @@ pluginManagement {
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.6.0" apply false
id "org.jetbrains.kotlin.android" version "2.1.10" apply false
id "com.android.application" version "7.3.0" apply false
id "org.jetbrains.kotlin.android" version "1.8.22" apply false
}
include ":app"

View File

@@ -17,7 +17,8 @@
"uidai",
"UIDAI",
"Unique Identification Authority of India"
]
],
"hex": "FBB401"
},
{
"title": "Accredible",
@@ -56,7 +57,8 @@
},
{
"title": "Amtrak",
"slug": "amtrak"
"slug": "amtrak",
"hex": "003A5D"
},
{
"title": "Animal Crossing",
@@ -67,6 +69,10 @@
"BellTree Forums"
]
},
{
"title": "AnimeZ.to",
"slug": "animez"
},
{
"title": "Ankama",
"slug": "ankama"
@@ -88,6 +94,13 @@
"Docaposte AR24"
]
},
{
"title": "Art Fight",
"slug": "art_fight",
"altNames": [
"ArtFight"
]
},
{
"title": "Aruba",
"slug": "aruba",
@@ -156,6 +169,14 @@
"Blizzard"
]
},
{
"title": "BBS.NGA",
"slug": "bbs_nga",
"altNames": [
"NGA玩家社区",
"NGA社区"
]
},
{
"title": "Belo"
},
@@ -300,7 +321,8 @@
},
{
"title": "Caltrain",
"slug": "caltrain"
"slug": "caltrain",
"hex": "E31837"
},
{
"title": "Canva"
@@ -365,7 +387,8 @@
"ClipperCard",
"clipper-card",
"Clipper Card"
]
],
"hex": "006298"
},
{
"title": "CloudAMQP"
@@ -382,11 +405,6 @@
{
"title": "CoinDCX"
},
{
"title": "CoinTracking",
"slug": "cointracking",
"altNames": ["cointracking.info", "Coin Tracking"]
},
{
"title": "colorado",
"altNames": [
@@ -415,7 +433,8 @@
},
{
"title": "Coolify",
"slug": "coolify"
"slug": "coolify",
"hex": "8C52FF"
},
{
"title": "Crowdpear"
@@ -464,6 +483,25 @@
"cwallet.com"
]
},
{
"title": "U.S. Department of Homeland Security",
"slug": "us_dhs",
"altNames": [
"DHS",
"dhs",
"United States Department of Homeland Security",
"uscis",
"USCIS",
"U.S. Citizenship and Immigration Services",
"cbp",
"CBP",
"U.S. Customs and Border Protection",
"U.S. Immigration and Customs Enforcement",
"ice",
"ICE"
],
"hex": "005189"
},
{
"title": "DCS",
"altNames": [
@@ -509,7 +547,8 @@
"altNames": [
"Domino's",
"Domino's Pizza"
]
],
"hex": "0B648F"
},
{
"title": "Doppler"
@@ -532,7 +571,8 @@
"Dunkin'",
"Dunkin",
"Dunkin Donuts"
]
],
"hex": "C63663"
},
{
"title": "eBay"
@@ -598,7 +638,8 @@
},
{
"title": "Experian",
"slug": "experian"
"slug": "experian",
"hex": "AF1685"
},
{
"title": "Fanatical",
@@ -722,7 +763,8 @@
"altNames": [
"green man gaming",
"gmg"
]
],
"hex": "00E205"
},
{
"title": "Guideline"
@@ -740,11 +782,6 @@
{
"title": "Hivelocity"
},
{
"title": "HRDocumentBox",
"slug": "hrdocumentbox",
"altNames": ["HRDocumentBox", "HR Document Box"]
},
{
"title": "HSA Bank",
"slug": "hsa_bank",
@@ -854,7 +891,8 @@
},
{
"title": "Kayak",
"slug": "kayak"
"slug": "kayak",
"hex": "FF6900"
},
{
"title": "Keygen",
@@ -1050,13 +1088,6 @@
"MistralAI"
]
},
{
"title": "Mobile01",
"slug": "mobile01",
"altNames": [
"M01"
]
},
{
"title": "Mozilla"
},
@@ -1162,7 +1193,8 @@
"slug": "njtransit",
"altNames": [
"NJ Transit"
]
],
"hex": "1A2B57"
},
{
"title": "nordvpn",
@@ -1236,12 +1268,6 @@
"title": "Parqet",
"slug": "parqet"
},
{
"title": "Parallels",
"slug": "parallels",
"hex": "#E61E25",
"altNames": ["Parallels Desktop", "Parallels VM"]
},
{
"title": "Parsec"
},
@@ -1273,7 +1299,8 @@
"slug": "pcpartpicker",
"altNames": [
"PC Part Picker"
]
],
"hex": "EDA920"
},
{
"title": "Peerberry"
@@ -1381,13 +1408,6 @@
"r10.net"
]
},
{
"title": "RaiderIO",
"slug": "raider_io",
"altNames": [
"raider.io"
]
},
{
"title": "Raindrop.io",
"slug": "raindrop_io",
@@ -1490,7 +1510,8 @@
"altNames": [
"onlinesbi",
"State Bank of India"
]
],
"hex": "12A8E0"
},
{
"title": "SEI",
@@ -1532,8 +1553,7 @@
"title": "Skinport"
},
{
"title": "Skyscanner",
"hex": "0770E3"
"title": "Smogon"
},
{
"title": "SMSPool",
@@ -1592,7 +1612,8 @@
},
{
"title": "Supercell",
"slug": "supercell"
"slug": "supercell",
"hex": "000000"
},
{
"title": "Surfshark"
@@ -1675,7 +1696,8 @@
"altNames": [
"StoryGraph",
"TheStoryGraph"
]
],
"hex": "15919B"
},
{
"title": "tianyiyun",
@@ -1796,11 +1818,6 @@
"uollet.com.br"
]
},
{
"title": "VHV",
"slug": "vhv",
"altNames": ["VHV", "VHV Versicherung"]
},
{
"title": "Vikunja"
},
@@ -1855,7 +1872,8 @@
"Washington Metro",
"DC Metro",
"Washington Metropolitan Area Transit Authority"
]
],
"hex": "2D2D2D"
},
{
"title": "Wolvesville"
@@ -1975,10 +1993,6 @@
{
"title": "ISC2",
"slug": "isc2"
},
{
"title": "Allegro",
"slug": "allegro"
}
]
}
}

View File

@@ -1,8 +0,0 @@
<svg version="1.2" baseProfile="tiny-ps" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1386 1594" width="1386" height="1594">
<title>logo (15)-svg copy-svg</title>
<style>
tspan { white-space:pre }
.shp0 { fill: #ff5a00 }
</style>
<path id="Layer" fill-rule="evenodd" class="shp0" d="M1385.14 634.99L1385.14 1547.13C1385.14 1553.03 1384.01 1558.88 1381.76 1564.35C1379.45 1569.82 1376.13 1574.75 1372 1578.93C1367.82 1583.11 1362.83 1586.44 1357.36 1588.69C1351.89 1590.94 1346.04 1592.12 1340.14 1592.12L570.51 1592.12C534.63 1594.16 498.65 1593.2 462.98 1589.23C427.26 1585.26 391.98 1578.29 357.44 1568.42C322.9 1558.55 289.28 1545.79 256.88 1530.35C224.49 1514.85 193.44 1496.67 164.05 1475.97C137.02 1453.77 112.73 1428.52 91.6 1400.63C70.47 1372.8 52.66 1342.56 38.61 1310.54C24.56 1278.53 14.32 1244.96 8.1 1210.59C1.82 1176.16 -0.32 1141.14 1.61 1106.29L1.61 1101.41C1.61 641.05 502.94 580.24 666.61 580.24L1046.9 580.24L1046.9 546.83C1047.7 524.84 1045.5 502.8 1040.36 481.41C1035.21 460.01 1027.22 439.42 1016.54 420.17C1005.87 400.92 992.63 383.17 977.23 367.51C961.79 351.8 944.25 338.28 925.21 327.29C785.88 256.77 512.11 282.89 283.91 423.38C278.5 428.1 271.85 431.32 264.77 432.66C257.69 434 250.34 433.47 243.53 431.05C236.72 428.64 230.66 424.46 225.99 418.93C221.38 413.41 218.27 406.76 216.98 399.63L202.99 171.03C202.99 168.08 203.31 165.18 204.06 162.34C204.76 159.5 205.88 156.77 207.33 154.19C208.73 151.67 210.5 149.31 212.53 147.22C214.62 145.13 216.93 143.31 219.45 141.8C259.67 118.58 301.4 97.99 344.3 80.24C387.26 62.49 431.29 47.59 476.17 35.63C521.12 23.67 566.75 14.71 612.82 8.76C658.89 2.86 705.33 -0.03 751.78 0.13C937.98 0.13 1138.77 54.24 1238.52 163.09C1338.32 271.95 1384.55 429.44 1384.55 636.81L1385.14 634.99ZM1046.9 858.76L687.31 858.76C410.48 858.76 355.13 1022.96 355.13 1105.05C354.87 1119.64 356.37 1134.17 359.64 1148.38C362.91 1162.59 367.9 1176.32 374.49 1189.3C381.09 1202.33 389.24 1214.45 398.84 1225.44C408.39 1236.49 419.22 1246.25 431.18 1254.61C442.71 1263.35 454.94 1271.18 467.7 1277.99C480.47 1284.8 493.71 1290.65 507.39 1295.47C521.01 1300.25 535.06 1304 549.27 1306.63C563.48 1309.26 577.91 1310.76 592.39 1311.19L1046.9 1311.19L1046.9 858.76Z" />
</svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 25 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 35 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 50 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

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

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 25 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,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="katman_1" xmlns="http://www.w3.org/2000/svg" baseProfile="tiny" version="1.2" viewBox="0 0 295.13 303">
<!-- Generator: Adobe Illustrator 29.6.0, SVG Export Plug-In . SVG Version: 2.1.1 Build 207) -->
<g id="Logo_2ColorWhite">
<path d="M453,42.76h-59.41v218.34h32.58v-76h26.83c18.81,0,26.83,5.13,26.83,15.81v60.2h32.59v-60.21c0-18.45-8.75-27.41-15.75-31.17,7-3.85,15.75-10.31,15.75-28.75v-52.07c0-21.05-10.31-46.15-59.42-46.15ZM479.83,140.98c0,10.67-8,13.18-26.83,13.18h-26.83v-80.47h26.83c18.81,0,26.83,4.54,26.83,15.22v52.07Z" fill="#fff"/>
<path d="M607.59,39.5c-39.84,0-62.73,18-62.73,49.41v172.19h32.58v-76h60.31v76h32.58V88.91c-.01-31.41-22.88-49.41-62.74-49.41ZM637.75,154.15h-60.3v-65.24c0-13,9-18.54,30.15-18.54s30.15,5.54,30.15,18.54v65.24Z" fill="#fff"/>
<polygon points="702.87 73.69 716.14 73.69 716.14 230.17 702.87 230.17 702.87 261.1 761.99 261.1 761.99 230.17 748.72 230.17 748.72 73.69 761.99 73.69 761.99 42.76 702.87 42.76 702.87 73.69" fill="#fff"/>
<path d="M857.66,42.76h-62.73v218.34h62.73c39.87,0,62.74-18,62.74-49.46v-119.42c0-31.42-22.87-49.46-62.74-49.46ZM887.8,211.64c0,13-9,18.53-30.14,18.53h-30.14V73.69h30.14c21.14,0,30.14,5.54,30.14,18.53v119.42Z" fill="#fff"/>
<path d="M953.52,92.22v119.42c0,31.42,22.87,49.46,62.74,49.46h49.49v-30.93h-49.45c-21.14,0-30.16-5.54-30.16-18.53v-40.65h73v-30.93h-73v-47.84c0-13,9-18.53,30.16-18.53h49.45v-30.93h-49.45c-39.91,0-62.78,18.04-62.78,49.46Z" fill="#fff"/>
<path d="M1158.23,42.81h-59.42v218.34h32.6v-76.36h26.82c18.81,0,26.84,4.55,26.84,15.22v61.14h32.58v-61.14c0-18.44-8.75-26.82-15.74-30.57,7-3.85,15.74-12.35,15.74-30.79v-49.69c0-21.05-10.32-46.15-59.42-46.15ZM1185.07,138.65c0,10.67-8,15.22-26.84,15.22h-26.82v-80.13h26.82c18.81,0,26.84,4.54,26.84,15.22v49.69Z" fill="#fff"/>
<rect x="1250.28" y="201.98" width="32.58" height="59.12" fill="#fff"/>
<polygon points="1315.82 73.69 1329.08 73.69 1329.08 230.17 1315.82 230.17 1315.82 261.1 1374.93 261.1 1374.93 230.17 1361.67 230.17 1361.67 73.69 1374.93 73.69 1374.93 42.76 1315.82 42.76 1315.82 73.69" fill="#fff"/>
<path d="M1470.75,39.5c-39.85,0-62.72,18-62.72,49.46v126c0,31.43,22.87,49.45,62.72,49.45s62.74-18,62.74-49.45v-126c-.03-31.46-22.9-49.46-62.74-49.46ZM1500.9,215.01c0,13-9,18.53-30.15,18.53s-30.14-5.54-30.14-18.53v-126c0-13,9-18.54,30.14-18.54s30.15,5.54,30.15,18.54v126Z" fill="#fff"/>
<path d="M292.75,118.28c1.83-2.01,2.65-4.74,2.23-7.43-.21-.81-.41-1.63-.63-2.44-.97-2.59-3.07-4.58-5.7-5.42l-28-8.45c-6.93-2.1-11.04-9.23-9.39-16.28l6.67-28.47c.56-2.32.21-4.77-1-6.83-.81-1.37-1.96-2.51-3.33-3.32-2.06-1.21-4.5-1.57-6.82-1l-28.47,6.67c-7.05,1.66-14.18-2.46-16.27-9.39l-8.46-28c-.83-2.57-2.76-4.64-5.28-5.63-.91-.25-1.83-.46-2.74-.7-2.63-.37-5.3.45-7.27,2.23l-21.32,20c-5.28,4.96-13.51,4.96-18.79,0L116.86,3.82c-1.97-1.78-4.64-2.6-7.27-2.23-.91.24-1.83.45-2.73.7-2.52.99-4.46,3.05-5.29,5.63l-8.46,28c-2.09,6.94-9.22,11.05-16.27,9.39l-28.47-6.71c-2.32-.56-4.77-.21-6.83,1-1.37.81-2.52,1.95-3.33,3.32-1.21,2.06-1.56,4.51-1,6.83l6.67,28.48c1.65,7.06-2.48,14.19-9.43,16.27l-28,8.45c-2.64.85-4.74,2.86-5.7,5.46-.22.81-.42,1.63-.63,2.44-.42,2.69.4,5.42,2.23,7.43l20,21.32c4.96,5.28,4.96,13.51,0,18.79l-20,21.32c-1.86,2.04-2.69,4.82-2.23,7.55.2.74.38,1.49.58,2.23.96,2.63,3.08,4.67,5.75,5.51l28,8.46c6.93,2.09,11.05,9.22,9.39,16.27l-6.67,28.47c-.6,2.56-.07,5.25,1.46,7.39,2.17,3.13,6.02,4.64,9.74,3.8l47.08-5.1c2.39-.24,4.14-2.36,3.93-4.76-1.57-17.27-9-81.84-11.73-105.94-.66-5.76,1.5-11.49,5.8-15.39l46.11-42c4.53-4.13,11.47-4.13,16,0l46.05,42c4.29,3.89,6.45,9.61,5.79,15.37-2.75,24.08-10.09,88.68-11.65,106-.21,2.39,1.54,4.51,3.93,4.75l47.09,5.1c2.58.61,5.29.06,7.43-1.49.9-.63,1.67-1.4,2.3-2.3,1.53-2.14,2.06-4.84,1.46-7.4l-6.67-28.47c-1.65-7.05,2.46-14.17,9.39-16.26l28-8.46c2.67-.84,4.79-2.88,5.75-5.51.2-.74.38-1.49.58-2.24.45-2.72-.37-5.5-2.23-7.54l-20-21.32c-4.96-5.28-4.96-13.51,0-18.79l19.97-21.36Z" fill="#e5a024"/>
<path d="M152.13,125.06c-2.15-2.52-5.94-2.81-8.46-.66-.24.2-.46.42-.66.66l-15.81,18.18c-3.17,3.64-4.78,8.38-4.49,13.2l8,135.87c.33,4.92,4.32,8.8,9.25,9,2.5.13,5.02.19,7.56.2,2.54,0,5.07-.06,7.6-.2,4.93-.19,8.93-4.07,9.25-9l8.11-135.81c.28-4.83-1.34-9.57-4.51-13.22l-15.84-18.22Z" fill="#808080"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.2 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-376.452 18.166 399.284 251.868"><path d="M195.1 220c2.1 0 4.1-.5 6-1.6l21.9-12.6c4.4-2.5 9.5-3.6 14.6-3 26.6 3.1 45.2 8.1 50.7 9.7 1.1.3 2.4-.1 3.1-1 .9-1.1 2-2.9 2.9-5.5.8-2.5.9-4.6.8-6.1-.1-1.2-.9-2.3-2.1-2.6-8.6-2.5-46.7-12.8-97.9-12.8s-89.3 10.3-97.9 12.8c-1.2.3-2 1.4-2.1 2.6-.1 1.4 0 3.5.8 6.1.8 2.6 2 4.4 2.9 5.5.7.9 2 1.3 3.1 1 5.5-1.6 24.2-6.6 50.7-9.7 5.1-.6 10.2.5 14.6 3l21.9 12.6c1.9 1.1 4 1.6 6 1.6zM158.6 149.1c1.2 2.1 3.1 3.5 5.3 4.1 2.2.6 4.5.3 6.6-.9 2.1-1.2 3.5-3.1 4.1-5.3.6-2.2.3-4.5-.9-6.6L154 106.3c-.6-1.1-1.9-1.5-3.1-1.4-1.6.1-3.8.9-6.4 2.4-2.6 1.5-4.4 3-5.3 4.3-.7 1-.9 2.3-.3 3.4l19.7 34.1zM140.6 173.5c2.1 1.2 4.5 1.4 6.6.9 2.2-.6 4.1-2 5.3-4.1 1.2-2.1 1.4-4.5.9-6.6-.5-2.1-2-4.1-4.1-5.3l-34.1-19.7c-1.1-.6-2.4-.4-3.4.3-1.3.9-2.8 2.7-4.3 5.3-1.5 2.6-2.3 4.8-2.4 6.4-.1 1.3.4 2.5 1.4 3.1l34.1 19.7zM203.8 137c0 2.4-1 4.6-2.5 6.2-1.6 1.6-3.7 2.5-6.2 2.5-2.4 0-4.6-1-6.2-2.5-1.6-1.6-2.5-3.7-2.5-6.2V97.7c0-1.3.8-2.3 2-2.8 1.4-.7 3.7-1.1 6.7-1.1s5.3.4 6.7 1.1c1.1.6 2 1.5 2 2.8V137zM231.6 149.1c-1.2 2.1-3.1 3.5-5.3 4.1-2.2.6-4.5.3-6.6-.9-2.1-1.2-3.5-3.1-4.1-5.3-.6-2.2-.3-4.5.9-6.6l19.7-34.1c.6-1.1 1.9-1.5 3.1-1.4 1.6.1 3.8.9 6.4 2.4 2.6 1.5 4.4 3 5.3 4.3.7 1 .9 2.3.3 3.4l-19.7 34.1zM249.6 173.5c-2.1 1.2-4.5 1.4-6.6.9-2.2-.6-4.1-2-5.3-4.1-1.2-2.1-1.4-4.5-.9-6.6.6-2.2 2-4.1 4.1-5.3l34.1-19.7c1.1-.6 2.4-.4 3.4.3 1.3.9 2.8 2.7 4.3 5.3 1.5 2.6 2.3 4.8 2.4 6.4.1 1.3-.4 2.5-1.4 3.1l-34.1 19.7z" class="st0" style="fill:#0770e3" transform="translate(-566.187 -169.038) scale(1.99578)"/></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="451.00259" height="507.332" viewBox="0 0 451.00259 507.332" id="svg2">
<defs id="defs4"/>
<metadata id="metadata7">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
</cc:Work>
</rdf:RDF>
</metadata>
<g transform="translate(-197.35585,-58.696183)" id="layer1">
<g transform="translate(28.601602,6.2831826)" id="g2986">
<g id="g2988">
<g id="g2990">
<path d="m 284.953,425.625 c -41.441,-0.008 -74.219,-15.391 -94.77,-44.48 -23.637,-33.461 -28.066,-83.176 -11.559,-129.75 21.262,-60.016 68.266,-89.355 68.742,-89.641 l 2.801,-1.703 4.555,-14.98 21.422,4.02 14.844,29.734 -0.773,5.273 c -0.738,4.98 -1.48,9.875 -2.215,14.695 l -0.191,1.238 c -5.277,34.695 -9.832,64.66 -6.102,82.488 2.242,10.711 7.199,17.898 15.895,22.906 2.984,-3.594 5.02,-5.305 7.535,-5.305 h 0.812 l 0.98,0.34 c 3.582,1.434 4.047,5.508 3.922,10.246 0.348,0.098 0.703,0.199 1.07,0.289 6.363,1.621 11.062,5.375 13.602,10.852 4.191,9.082 0.234,17.125 -3.254,24.215 -2.578,5.238 -6.379,12.953 -8.754,23.418 3.586,6.008 4.141,11.75 3.934,15.641 -0.297,5.516 -2.406,11.066 -5.996,15.848 1.102,4.875 0.484,9.473 -1.844,13.688 -5.285,9.566 -15.68,10.465 -19.094,10.754 -1.574,0.137 -3.34,0.215 -5.262,0.215 h -0.3 z" id="path2992" style="fill:#260859"/>
</g>
<g id="g2994">
<path d="m 506.766,425.695 c -6.77,0 -12.57,-2.73 -16.773,-7.902 -8.246,-10.133 -6.812,-26.621 -3.918,-41.938 -3.145,-2.297 -7.34,-5.594 -9.633,-10.934 l -5.355,-12.438 11.875,-6.527 c 24.914,-13.723 34.227,-39.723 27.668,-77.289 -2.957,-4.148 -7.086,-11.844 -10.824,-25.562 -2.727,-10.008 -13.16,-72.691 -7.508,-83.227 1.012,-1.898 5.035,-8.109 14.039,-8.109 5.695,0 19.23,3.664 28.004,12.398 0.246,-0.012 0.488,-0.016 0.734,-0.016 5.488,0 9.648,2.668 13.672,5.242 l 0.477,0.301 c 1.07,0.68 2.219,1.41 3.492,2.164 2.246,1.336 6.668,3.961 10.598,9.719 6.301,1.035 11.359,5.949 20.273,15.086 0.207,0.219 0.996,1.027 1.203,1.227 2.219,2.195 3.977,5.051 5.602,9.125 11.438,4.383 18.34,21.609 19.629,27.852 l 0.508,1.938 c 15.383,58.23 11.477,106.727 -11.297,140.25 -18.512,27.266 -48.637,43.574 -89.535,48.465 -1.045,0.117 -1.994,0.175 -2.931,0.175 l 0,0 z" id="path2996" style="fill:#260859"/>
</g>
</g>
<path d="M 382.699,555.371 C 362.824,548.375 188.613,484.344 188.613,390.375 l 0.012,-281.641 c 0,-25.367 21.531,-46.004 47.996,-46.004 16.855,0 32.289,8.32 40.957,21.902 31.453,-3.801 73.332,-11.934 99.66,-23.809 l 2.559,-1.129 15.438,-7.281 16.172,7.629 c 26.121,12.301 69,20.699 101.461,24.602 8.672,-13.59 24.102,-21.914 40.949,-21.914 26.473,0 48.008,20.551 48.008,45.812 l -0.027,281.832 c 0,94.301 -174.176,158.012 -194.039,164.965 l -12.523,4.406 -12.537,-4.374 z" id="path2998" style="fill:#260859"/>
<path d="M 389.637,535.469 C 371.207,528.989 209.688,469.871 209.688,390.375 L 209.7,108.734 c 0,-13.93 12.086,-24.93 26.922,-24.93 14.336,0 26.137,10.309 26.867,23.469 l 0.004,0.012 c 35.363,-3.055 88.648,-12.023 122.41,-27.25 l 2.426,-1.07 6.906,-3.254 7.176,3.387 c 33.441,15.754 87.988,25.031 124.539,28.188 h 0.004 c 0.73,-13.168 12.527,-23.48 26.863,-23.48 14.852,0 26.934,11.098 26.934,24.738 l -0.027,281.832 c 0,79.676 -161.52,138.625 -179.938,145.082 l -5.57,1.961 -5.579,-1.95 z" id="path3000" style="fill:#7c3a00"/>
<path d="m 395.156,112.82 -1.527,0.621 c -37.711,15.406 -92.113,24.406 -127.242,27.43 l -22.969,1.984 -0.008,130.859 H 395.156 V 112.82 z" id="path3002" style="fill:#ffef6f"/>
<path d="m 395.223,75.715 -6.895,3.25 -2.426,1.07 c -33.762,15.227 -87.047,24.195 -122.41,27.25 l -0.004,-0.012 c -0.73,-13.16 -12.531,-23.469 -26.867,-23.469 -14.836,0 -26.922,11 -26.922,24.93 l -0.012,281.641 c 0,79.496 161.52,138.613 179.949,145.094 l 5.578,1.949 0.008,-0.004 V 75.715 z" id="path3004" style="fill:#e8941a"/>
<g id="g3006">
<path d="m 553.816,100.664 c -5.395,0 -9.801,3.312 -10.035,7.539 l -0.941,17.375 -17.34,-1.5 c -38.246,-3.301 -94.871,-13.051 -130.277,-29.734 -0.773,0.363 -1.609,0.707 -2.402,1.062 0.016,-0.004 0.031,-0.012 0.043,-0.016 v 307.098 l 171.008,-126.707 0.02,-167.238 c -0.001,-4.27 -4.615,-7.879 -10.076,-7.879 z" id="path3008" style="fill:#e8941a"/>
</g>
<path d="M 392.863,397.402 V 95.391 c -35.527,16.031 -90.5,25.457 -127.926,28.688 l -17.336,1.5 -0.941,-17.367 c -0.234,-4.234 -4.645,-7.547 -10.039,-7.547 -5.766,0 -10.082,3.891 -10.09,7.219 l 0.027,0.852 -0.004,152.738 166.309,135.928 z" id="path3010" style="fill:#ffef6f"/>
<path d="m 525.5,124.078 c -38.246,-3.301 -94.871,-13.051 -130.277,-29.734 -0.492,0.23 -1.031,0.449 -1.527,0.676 v 41.531 l 30.055,-1.555 113.195,21.496 10.082,-13.633 -4.188,-17.281 -17.34,-1.5 z" id="path3012" style="fill:#e8941a"/>
<path d="m 393.695,95.02 c -35.492,16.262 -91.043,25.805 -128.758,29.059 l -17.336,1.5 -4.184,17.277 19.438,6.918 102.445,-11.754 28.395,-1.469 V 95.02 z" id="path3014" style="fill:#ffffff"/>
<path d="m 226.555,243.211 -0.008,147.652 c 0,55.215 105.336,106.918 168.656,129.176 63.324,-22.238 168.66,-73.918 168.66,-129.176 l 0.016,-147.652 H 226.555 z" id="path3016" style="fill:#ffd26c"/>
<path d="M 393.746,508.047 C 318.914,480.473 243.406,435.543 243.406,397.313 l 0.012,-254.457 22.969,-1.984 c 35.129,-3.023 89.531,-12.023 127.242,-27.43 l 1.594,-0.648 1.59,0.648 c 37.711,15.406 92.109,24.406 127.242,27.43 l 22.973,1.988 -0.023,254.453 c 0,38.266 -75.508,83.188 -150.344,110.734 l -1.457,0.535 -1.458,-0.535 z" id="path3018" style="fill:#ffffff"/>
<path d="m 524.055,140.871 c -35.133,-3.023 -89.531,-12.023 -127.242,-27.43 l -1.59,-0.648 -1.594,0.648 1.527,-0.621 v 160.895 h 151.859 l 0.012,-130.855 -22.972,-1.989 z" id="path3020" style="fill:#ffd26c"/>
<path d="m 395.156,112.82 -1.527,0.621 c -37.711,15.406 -92.113,24.406 -127.242,27.43 l -22.969,1.984 -0.008,130.859 H 395.156 V 112.82 z" id="path3022" style="fill:#ffef6f"/>
<linearGradient x1="395.21631" y1="132.92529" x2="395.21631" y2="491.23761" id="SVGID_1_" gradientUnits="userSpaceOnUse">
<stop id="stop3025" style="stop-color:#e8941a;stop-opacity:1" offset="0"/>
<stop id="stop3027" style="stop-color:#ffef6f;stop-opacity:1" offset="1"/>
</linearGradient>
<path d="M 395.203,494.371 C 315.765,464.609 256.051,422.691 256.051,396.586 l 0.012,-242.137 11.41,-0.984 c 34.82,-2.996 88.879,-11.863 127.75,-27.043 38.859,15.18 92.914,24.047 127.742,27.043 l 11.418,0.988 -0.023,242.133 c -10e-4,26.133 -59.715,68.051 -139.157,97.785 l 0,0 z" id="path3029" style="fill:url(#SVGID_1_)"/>
<path d="m 534.359,377.328 c 0,26.133 -59.715,68.051 -139.156,97.785 C 315.777,445.355 256.07,403.449 256.051,377.34 v 23.805 c 0,26.102 59.715,68.02 139.152,97.785 79.441,-29.734 139.156,-71.652 139.156,-97.785 l 0.023,-246.691 0,0 -0.023,222.874 z" id="path3031" style="fill:#260859"/>
<path d="m 395.156,126.445 c -38.867,15.164 -92.883,24.023 -127.684,27.02 l -11.41,0.984 v 16.746 l 10.133,-0.867 c 35.152,-2.996 89.707,-11.855 128.961,-27.02 v -16.863 z" id="path3033" style="fill:#a84d10"/>
<path d="m 522.965,153.465 c -34.828,-2.996 -88.883,-11.863 -127.742,-27.043 -0.223,0.086 -0.457,0.164 -0.68,0.25 0.199,-0.074 0.41,-0.148 0.613,-0.227 v 16.863 c 0.02,-0.008 0.043,-0.016 0.066,-0.023 39.25,15.18 93.844,24.047 129.023,27.043 l 10.137,0.871 v -16.746 l -11.417,-0.988 z" id="path3035" style="fill:#a84d10"/>
<path d="m 256.062,158.086 -0.012,238.5 c 0,7.613 5.105,16.57 14.262,26.176 1.164,0.109 2.312,0.242 3.492,0.328 0.074,1.215 0.168,2.344 0.277,3.438 23.133,22.137 66.586,47.148 118.852,66.977 l -0.059,-1.766 c -0.59,-18.352 -2.348,-35.594 -4.691,-46.121 -5.438,-24.406 -22.613,-48.82 -37.359,-62.367 -6.184,-15.457 -1.742,-25.371 4.391,-39.07 1.871,-4.168 3.992,-8.887 5.699,-13.855 5.145,-14.93 4.266,-38.211 -1.984,-53.98 -2.898,-9.637 -9.184,-16.973 -16.832,-19.625 -2.328,-0.777 -5.027,-1.312 -8.23,-1.625 -3.215,-10.938 -1.609,-22.059 -1.598,-22.148 l 1.754,-10.398 -9.758,-3.961 c -0.977,-0.398 -9.941,-3.902 -23.02,-3.902 -6.027,0 -12.105,0.785 -18.117,2.34 0.82,-5.617 1.695,-11.391 2.598,-17.309 0,0 1.664,-10.949 2.402,-15.922 l 0.676,-4.617 -15.496,-26.328 c 0,0 -3.242,0.398 -5.836,0.617 l -11.411,4.618 z" id="path3037" style="fill:#260859"/>
<path d="m 514.695,428.105 c 0.016,-1.758 0.035,-3.516 -0.082,-5.402 2.242,-0.328 4.438,-0.699 6.609,-1.102 8.461,-9.164 13.137,-17.707 13.137,-25.016 l -1.562,-226.52 c 0,0 2.516,-0.133 2.234,-0.102 -3.75,-10.566 -23.34,-16.086 -28.695,-16.086 -7.617,0 -11.059,4.895 -12.184,6.996 -5.09,9.496 4.488,69.965 7.688,81.676 0.309,1.141 0.621,2.191 0.938,3.234 l -1.672,8.418 c -14.316,-13.652 -32.395,-28.645 -42.766,-28.645 -0.656,0 -1.289,0.055 -1.898,0.156 -2.648,0.461 -4.789,1.961 -6.016,4.215 -1.777,3.258 -1.703,7.801 0.27,14.133 -5.043,-1.027 -11.129,-1.98 -16.34,-1.98 -6.387,0 -10.586,1.453 -12.836,4.434 -4.473,5.934 -2.328,15.238 6.367,27.66 2.562,3.668 5.789,7.285 8.969,10.848 0.66,0.746 1.328,1.492 1.992,2.242 -9.152,14.402 -11.535,36.027 -6.352,58.285 2.27,9.738 5.41,16.656 8.188,22.77 1.766,3.883 3.203,7.047 4.09,10.273 -21.77,18.578 -37.285,42.938 -42.648,67.016 -2.184,9.785 -3.836,25.16 -4.547,42.199 l -0.23,5.742 c 51.096,-19.35 93.811,-43.674 117.346,-65.444 z" id="path3039" style="fill:#260859"/>
<g id="g3041">
<path d="m 321.699,323.621 c -1.984,-4.289 -5.723,-7.242 -10.809,-8.539 -19.477,-4.91 -29.746,-14.688 -33.309,-31.699 -3.887,-18.574 0.723,-48.887 6.062,-83.988 l 0.188,-1.234 c 0.734,-4.816 1.477,-9.707 2.211,-14.672 l 0.582,-3.965 -13.316,-26.676 -15.652,-2.938 -3.922,12.906 -4.168,2.527 c -0.457,0.281 -46.105,28.566 -66.969,87.457 -16.059,45.312 -11.832,93.551 11.023,125.91 19.73,27.922 51.32,42.691 91.348,42.699 1.902,0.008 3.645,-0.066 5.184,-0.195 4.969,-0.43 12.004,-1.789 15.77,-8.598 2.121,-3.844 2.418,-7.98 0.891,-12.609 3.871,-4.461 6.141,-9.797 6.426,-15.113 0.195,-3.613 -0.395,-9.031 -4.211,-14.613 2.449,-11.852 6.652,-20.379 9.449,-26.062 3.375,-6.86 6.57,-13.344 3.222,-20.598 z" id="path3043" style="fill:#260859"/>
<g id="g3045">
<path d="m 199.93,259.562 c 14.34,-66.531 55.953,-77.508 55.953,-77.508 l -1.012,36.066 0.816,76.336 c 0,0 -2.602,60.848 30.262,73.891 32.863,13.039 6.941,42.215 -36.23,31.109 C 208.5,389.602 184.465,330.16 199.93,259.562 z" id="path3047" style="fill:#ffffff"/>
<g id="g3049">
<path d="m 228.879,317.406 c -10.066,-45.742 11.844,-91.457 22.941,-105.285 l 13.945,-45.91 7.914,15.453 c -4.523,30.586 -9.375,58.598 -9.957,80.766 -0.121,4.418 0.922,20.125 1.629,23.516 3.336,15.93 11.039,27.066 24.359,34.395 2.242,1.234 13.094,-16.984 15.656,-15.965 3.352,1.344 -1.461,21.836 2.469,22.828 9.133,2.305 -6.898,13.684 -11.938,45.445 -21.198,1.91 -56.975,-9.61 -67.018,-55.243 z" id="path3051" style="fill:#f26531"/>
</g>
<path d="m 194.371,256.984 c 19.648,-55.469 61.68,-80.957 61.68,-80.957 l -0.434,15.422 c -15.742,12.766 -62.27,71.184 -44.375,141.27 13.469,48.656 52.797,63.223 80.523,57.949 -4.102,9.059 14.18,18.254 -6.789,18.254 -91.675,-0.02 -114.8,-83.645 -90.605,-151.938 z" id="path3053" style="fill:#7ac143"/>
</g>
<polygon points="213.434,210.594 205.309,222.129 239.594,232.855 " id="polygon3055" style="fill:#260859"/>
<polygon points="191.312,240.535 186.168,257.379 230.988,256.758 " id="polygon3057" style="fill:#260859"/>
<polygon points="183.648,279.039 183.082,296.645 226.18,284.332 " id="polygon3059" style="fill:#260859"/>
<polygon points="180.789,326.434 186,346.004 229.383,318.148 " id="polygon3061" style="fill:#260859"/>
<polygon points="201.324,373.969 214.367,389.453 241.773,345.785 " id="polygon3063" style="fill:#260859"/>
<polygon points="241.258,405.695 259.137,409.742 267.953,367.039 " id="polygon3065" style="fill:#260859"/>
</g>
<path d="m 324.59,268.086 c 0.148,0.016 0.281,0.008 0.438,0.023 -9.18,-17.043 -5.715,-37.352 -5.715,-37.352 0,0 -16.691,-6.77 -37.332,0.254 -24.391,8.301 -27.098,26.691 -24.246,32.094 2.688,5.09 9.637,6.027 15.934,2.34 3.547,9.219 8,15.848 18.32,24.191 l 34.66,-20.137 c -10e-4,10e-4 -0.837,-0.394 -2.059,-1.413 z" id="path3067" style="fill:#fff200"/>
<path d="m 274.98,347.574 c -5.398,0 -8.523,-1.82 -9.355,-2.379 l -9.891,-6.449 12.168,-6.41 c 5.203,-1.285 10.617,-7.621 15.832,-14.719 -1.098,0.18 -2.164,0.363 -3.195,0.535 -6.023,1.031 -11.086,1.895 -14.895,1.895 -0.688,0 -1.328,-0.031 -1.918,-0.082 -0.203,-0.02 -0.395,-0.027 -0.59,-0.027 -4.445,0 -10.258,3.727 -12.125,5.164 l -6.609,5.445 -4.531,-8.77 c -0.234,-0.688 -2.207,-6.969 1.93,-14.664 3.105,-5.758 12.41,-13.875 23.41,-13.875 1.82,0 3.633,0.219 5.387,0.652 0.594,0.148 1.184,0.223 1.734,0.223 2.828,0 5.781,-1.98 8.781,-5.883 0.738,-1.004 1.242,-1.891 1.648,-2.598 0.473,-0.82 0.875,-1.5 1.395,-2.191 1.762,-2.109 4.008,-3.098 6.93,-3.098 5.004,0 11.262,2.648 13.82,10.074 l 0,0 c 0.008,0 0.719,1.465 4.141,4.703 3.637,0.766 6.613,2.043 8.863,3.809 3.297,2.598 5.059,6.297 4.953,10.43 -0.207,8.285 -7.871,17.668 -23.434,28.684 -11.148,7.875 -19.449,9.531 -24.449,9.531 l 0,0 z" id="path3069" style="fill:#260859"/>
<path d="m 285.051,298.215 c -8.113,-6.562 -13.383,-12.48 -17.387,-19.559 -0.559,0.035 -1.121,0.059 -1.676,0.059 -7.941,0 -14.508,-3.812 -18.008,-10.461 -2.953,-5.582 -2.887,-13.828 0.176,-21.527 2.715,-6.844 10.266,-19.348 30.266,-26.16 7.363,-2.504 15.043,-3.773 22.824,-3.773 12.699,0 21.285,3.363 22.227,3.746 l 8.191,3.324 -1.473,8.734 c -0.02,0.137 -2.246,15.293 3.441,28.035 l 16.324,8.004 -17.734,10.391 -41.266,23.961 -5.905,-4.774 z" id="path3071" style="fill:#260859"/>
<path d="m 313.297,327.484 c -4.66,0 -5.777,-4.406 -6.758,-8.293 -0.754,-2.98 -1.535,-6.062 -3.594,-8.117 -7.707,-7.703 -18.688,-12.191 -18.801,-12.238 l -1.008,-0.406 -0.25,-1.062 c -1.91,-8.031 -0.074,-15.875 5.312,-22.695 8.305,-10.508 25,-17.848 40.602,-17.848 4.613,0 8.863,0.637 12.629,1.895 11.438,3.969 18.797,19.078 16.785,34.398 -2.59,19.672 -19.195,32.516 -44.418,34.352 l -0.499,0.014 z" id="path3073" style="fill:#260859"/>
<path d="m 390.77,491.805 c -0.586,-18.211 -2.32,-35.305 -4.645,-45.73 -5.391,-24.207 -22.441,-48.285 -37.074,-61.586 -6.785,-16.547 -1.922,-27.41 4.227,-41.141 1.859,-4.137 3.961,-8.82 5.645,-13.711 6.371,-18.496 3.301,-52.016 -9.367,-64.766 l -0.875,-0.883 -17.277,4.875 -0.285,1.207 c -3.629,15.34 -12.52,35.328 -19.969,40.625 l -5.223,3.711 0.672,6.355 c 1.371,13.16 -5.613,28.898 -23.094,64.328 -6.949,14.074 -9.164,28.023 -7.043,43.664 23.328,21.27 64.762,44.902 114.336,63.93 l -0.028,-0.878 z" id="path3075" style="fill:#260859"/>
<path d="m 286.379,296.578 c -8.293,-6.707 -13.605,-12.801 -17.535,-20.16 -0.957,0.125 -1.914,0.188 -2.855,0.188 -7.129,0 -13.016,-3.398 -16.145,-9.336 -2.672,-5.051 -2.57,-12.621 0.27,-19.766 2.586,-6.512 9.793,-18.406 28.988,-24.941 7.148,-2.434 14.594,-3.664 22.145,-3.664 12.223,0 20.52,3.219 21.426,3.59 l 6.637,2.691 -1.195,7.066 c -0.023,0.141 -2.43,16.492 3.918,29.945 l 13.477,6.609 -14.352,8.406 -40,23.23 -4.779,-3.858 z" id="path3077" style="fill:#260859"/>
<path d="m 324.59,268.086 c 0.148,0.016 0.281,0.008 0.438,0.023 -9.18,-17.043 -5.715,-37.352 -5.715,-37.352 0,0 -16.691,-6.77 -37.332,0.254 -24.391,8.301 -27.098,26.691 -24.246,32.094 2.688,5.09 9.637,6.027 15.934,2.34 3.547,9.219 8,15.848 18.32,24.191 l 34.66,-20.137 c -10e-4,10e-4 -0.837,-0.394 -2.059,-1.413 z" id="path3079" style="fill:#fff200"/>
<path d="m 291.426,228.664 c -3.023,0.5 -6.176,1.234 -9.445,2.348 -1.793,0.609 -3.449,1.281 -5.012,1.988 0.133,0.762 0.27,1.52 0.402,2.305 2.273,13.105 5.395,30.973 23.766,49.016 l 3.77,-2.191 4.488,-4.691 c -0.477,-0.453 -0.945,-0.914 -1.398,-1.371 -15.052,-15.072 -17.841,-27.463 -16.571,-47.404 z" id="path3081" style="fill:#f26531"/>
<path d="m 319.312,230.758 c 0,0 -4.73,-1.898 -12.234,-2.641 -2.945,19.641 0.68,32.223 5.871,43.66 2.867,-2.016 6.352,-4.246 12.078,-3.668 -9.179,-17.043 -5.715,-37.351 -5.715,-37.351 z" id="path3083" style="fill:#f26531"/>
<path d="m 340.762,260.719 c -22.492,-7.508 -62.18,9.445 -55.824,36.164 0,0 11.375,4.582 19.496,12.699 5.488,5.477 3.191,16.223 9.211,15.781 55.078,-4.008 48.554,-57.203 27.117,-64.644 z" id="path3085" style="fill:#260859"/>
<path d="m 384.066,446.531 c -5.324,-23.91 -22.367,-47.836 -36.781,-60.797 -7.402,-17.637 -2.094,-29.484 4.07,-43.25 1.84,-4.102 3.926,-8.746 5.574,-13.535 6.051,-17.562 3.086,-50.559 -8.871,-62.594 l -14.891,4.199 c -3.703,15.652 -12.715,36.105 -20.797,41.855 l -4.219,3 0.543,5.133 c 1.426,13.711 -5.629,29.66 -23.301,65.484 -7.051,14.281 -9.199,28.594 -6.531,44.879 23.355,20.395 62.828,42.727 109.797,60.965 -0.671,-20.983 -2.706,-36.886 -4.593,-45.339 z" id="path3087" style="fill:#260859"/>
<path d="m 375.43,448.457 c -4.688,-21.027 -20.555,-44.578 -35.52,-57.488 -0.02,-0.051 -0.031,-0.094 -0.059,-0.145 -12.793,-28.352 1.895,-44.961 8.711,-64.754 5.188,-15.062 2.301,-44.332 -6.785,-53.473 -2.863,12.109 -12.199,38.438 -24.281,47.027 1.711,16.387 -6.383,34.281 -24.168,70.316 -7.707,15.625 -8.574,31.184 -3.348,49.906 22.02,16.477 53.324,33.613 89.688,48.441 -0.727,-17.475 -2.406,-31.607 -4.238,-39.83 z" id="path3089" style="fill:#f26531"/>
<path d="m 336.758,268.195 c -10.891,-5.066 -39.801,0.785 -49.402,24.723 0,0 8.891,5.105 14.688,12.75 3.91,5.168 3.672,14.082 8.707,14.211 42.866,1.105 42.554,-43.981 26.007,-51.684 z" id="path3091" style="fill:#f26531"/>
<path d="m 272.738,340.402 c -1.93,0 -3.652,-0.895 -4.738,-2.457 -1.965,-2.816 -0.754,-6.086 -0.109,-7.84 3.441,-9.297 12.891,-18.176 21.5,-20.219 l 16.016,-4.246 1.781,0.863 c 4.453,2.152 2.496,-3.094 5.336,-1.969 11.52,4.566 5.867,13.898 4.336,16.051 -3.465,4.875 -7.785,4.871 -10.066,5.266 -9.285,1.57 -14.492,4.105 -18.293,5.965 -1.504,0.734 -2.801,1.367 -4.184,1.898 -0.977,0.379 -3.066,2.02 -4.32,3 -2.829,2.224 -4.7,3.688 -7.259,3.688 l 0,0 z" id="path3093" style="fill:#260859"/>
<path d="m 304.859,311.324 -14.234,3.773 c -6.875,1.625 -14.824,9.062 -17.707,16.859 -2.891,7.805 4.785,-1.43 9.469,-3.234 4.668,-1.812 10.121,-5.887 23.5,-8.156 13.379,-2.265 -1.028,-9.242 -1.028,-9.242 z" id="path3095" style="fill:#f26531"/>
<path d="m 290.859,310.074 c 0,0 -11.062,22.945 -25.168,28.18 l 10.75,1.375 c 0,0 15.59,-9.383 18.441,-19.707 2.852,-10.312 2.551,-15.832 2.551,-15.832 l -6.574,5.984 z" id="path3097" style="fill:#260859"/>
<path d="m 313.492,304.547 c -6.148,-4.84 -21.82,-2.699 -21.82,-2.699 l 8.758,5.172 c -8.391,9.762 -18.191,29.141 -30.828,32.25 0,0 8.082,5.398 25.703,-7.062 17.621,-12.46 24.347,-22.825 18.187,-27.661 z" id="path3099" style="fill:#fff200"/>
<path d="m 289.879,287.703 c -0.773,1.035 -1.34,2.477 -3.102,4.871 -2.613,3.402 -8.828,10.496 -17.902,8.246 -9.074,-2.25 -18.012,4.523 -20.785,9.676 -2.77,5.152 -1.465,8.965 -1.465,8.965 0,0 9.391,-7.359 17.73,-6.609 8.348,0.758 32.059,-6.914 50.258,-4.016 0,0 -14.355,-10.16 -16.457,-16.086 -2.011,-5.848 -7.902,-5.488 -8.277,-5.047 z" id="path3101" style="fill:#fff200"/>
<g id="g3103">
<path d="m 318.129,275.305 c -8.238,10.934 -12.203,12.973 -19.973,17.445 18.227,33.57 52.637,-9.355 19.973,-17.445 z" id="path3105" style="fill:#260859"/>
</g>
<g id="g3107">
<path d="m 315.082,300.051 c -3.988,0 -7.168,-2.73 -9.383,-5.508 5.203,-3.199 9.039,-6.363 14.363,-13.004 4.559,1.859 6.637,4.664 6.188,8.344 -0.574,4.703 -5.578,10.168 -11.168,10.168 l 0,0 z" id="path3109" style="fill:#ffffff"/>
</g>
<path d="m 317.875,282.395 c -2.621,1.168 -5.152,2.633 -7.699,3.727 -1.414,0.609 -3.875,2.562 -3.633,3.16 1.148,2.824 3.023,5.551 6.082,6.75 0.297,0.117 0.602,0.211 0.906,0.289 0.695,-1.246 1.336,-2.582 1.898,-4.008 1.118,-2.86 2.009,-6.751 2.446,-9.918 z" id="path3111" style="fill:#260859"/>
<path d="m 313.707,296.379 c 0,-2.535 -0.289,-4.934 -0.781,-7.129 -2.305,2.059 -4.594,3.672 -7.227,5.293 1.91,2.398 4.551,4.75 7.801,5.352 0.125,-1.137 0.207,-2.305 0.207,-3.516 z" id="path3113" style="fill:#f37344"/>
<path d="m 280.828,251.062 c 0.438,9.141 4.355,19.59 12.043,29.02 l 4.793,-4.211 c -11.609,-7.101 -16.836,-24.809 -16.836,-24.809 z" id="path3115" style="fill:#260859"/>
<path d="m 291.141,238.789 c -1.156,10.66 1.484,23.461 8.672,35.766 l 6.305,-4 c -12.141,-10.336 -14.977,-31.766 -14.977,-31.766 z" id="path3117" style="fill:#260859"/>
<path d="m 306.738,231.996 c -2.785,10.348 -2.152,23.402 3.047,36.672 l 6.844,-2.973 c -10.399,-12.082 -9.891,-33.699 -9.891,-33.699 z" id="path3119" style="fill:#260859"/>
<path d="m 334.832,367.363 c 0.266,-6.996 2.133,-13.312 4.527,-19.387 0.395,-1.004 -7.34,5.734 -15.191,7.973 -7.262,2.07 -14.66,-0.41 -14.953,0.293 -2.434,5.727 -5.387,12.094 -8.852,19.297 19.012,1.656 27.176,-2.223 34.469,-8.176 z" id="path3121" style="fill:#7ac143"/>
<path d="m 337.445,353.391 c 1.25,-3.918 2.812,-7.699 4.465,-11.438 -12.93,7.711 -20.523,10.559 -30.961,10.07 -1.262,3.164 -2.719,6.547 -4.34,10.152 13.114,1.403 24.301,-3.511 30.836,-8.784 z" id="path3123" style="fill:#ffffff"/>
<path d="m 293.305,389.996 c -7.684,15.605 -8.547,31.148 -3.324,49.852 12.047,9.012 26.852,18.227 43.773,27.152 12.125,-36.82 -2.57,-65.309 -8.16,-75.688 -8.168,2.25 -33.199,11.153 -32.289,-1.316 z" id="path3125" style="fill:#ffffff"/>
<g id="g3127">
<path d="m 426.086,226.523 c -3.566,0 -6.266,-1.336 -7.719,-2.051 -0.879,-0.445 -2,-1.012 -7.145,-4.84 -5.227,1.496 -10.617,2.254 -16.043,2.254 -5.52,0 -10.984,-0.777 -16.266,-2.309 -5.227,3.891 -6.375,4.465 -7.148,4.855 -1.371,0.684 -4.199,2.09 -7.797,2.09 -4.008,0 -7.691,-1.621 -10.949,-4.805 -4.895,-4.824 -6.535,-9.34 -5.664,-15.602 0.137,-0.996 0.441,-2.527 1.691,-6.785 -1.613,-2.074 -3.102,-4.285 -4.441,-6.59 -9.844,-3.238 -12.664,-4.578 -14.113,-5.461 -4.582,-2.82 -6.859,-8.195 -6.98,-16.441 -0.117,-8.219 1.965,-13.617 6.363,-16.496 0.707,-0.461 1.859,-1.211 8.289,-4.105 0.246,-1.074 0.527,-2.141 0.832,-3.195 -5.164,-7.422 -5.906,-9.02 -6.309,-9.887 -1.41,-3.07 -2.191,-8.109 2.059,-14.746 1.551,-2.414 7.227,-10.281 15.102,-10.281 h 0.797 l 1.406,0.211 c 0.941,0.184 2.262,0.449 9.582,3.125 4.242,-2.965 8.844,-5.352 13.707,-7.109 2.277,-5.695 3.047,-6.969 3.422,-7.594 2.812,-4.617 8.301,-6.957 16.328,-6.957 8.25,0 13.824,2.352 16.57,6.988 0.398,0.676 1.055,1.781 3.363,7.566 4.855,1.758 9.449,4.141 13.676,7.098 7.227,-2.648 8.523,-2.91 9.391,-3.09 l 0.734,-0.148 1.395,-0.086 c 7.91,0 13.363,7.188 15.348,10.277 4.25,6.629 3.473,11.66 2.07,14.715 -0.418,0.906 -1.176,2.527 -6.289,9.871 0.312,1.074 0.594,2.156 0.844,3.246 6.473,2.906 7.566,3.625 8.297,4.105 4.398,2.875 6.48,8.273 6.359,16.496 -0.113,8.125 -2.453,13.648 -6.957,16.414 -1.016,0.625 -2.891,1.785 -14.141,5.484 -1.391,2.406 -2.957,4.711 -4.656,6.879 1.348,4.625 1.508,5.785 1.605,6.496 0.871,6.266 -0.762,10.777 -5.645,15.582 -3.269,3.201 -6.956,4.826 -10.968,4.826 l 0,0 z" id="path3129" style="fill:#260859"/>
<path d="m 426.086,224.414 c -3.094,0 -5.512,-1.203 -6.812,-1.844 -0.746,-0.379 -1.895,-0.953 -7.633,-5.262 -5.348,1.641 -10.875,2.473 -16.461,2.473 -5.676,0 -11.273,-0.848 -16.676,-2.527 -5.824,4.367 -6.977,4.941 -7.691,5.301 -1.324,0.656 -3.75,1.859 -6.844,1.859 -3.438,0 -6.621,-1.41 -9.477,-4.203 -4.41,-4.344 -5.828,-8.211 -5.051,-13.801 0.137,-1 0.48,-2.645 1.938,-7.531 -1.992,-2.461 -3.781,-5.105 -5.344,-7.887 -10.289,-3.363 -13.133,-4.711 -14.441,-5.512 -3.922,-2.41 -5.867,-7.207 -5.973,-14.668 -0.109,-7.441 1.664,-12.254 5.41,-14.707 0.672,-0.438 1.848,-1.199 8.965,-4.375 0.359,-1.711 0.801,-3.402 1.309,-5.059 -5.598,-8.008 -6.336,-9.613 -6.707,-10.41 -1.188,-2.582 -1.816,-6.879 1.922,-12.715 1.41,-2.195 6.527,-9.309 13.328,-9.309 h 0.797 l 1.051,0.18 c 0.832,0.164 2.242,0.457 10.258,3.406 4.551,-3.312 9.668,-5.977 14.992,-7.801 2.492,-6.301 3.273,-7.594 3.621,-8.176 2.402,-3.941 7.281,-5.934 14.523,-5.934 7.453,0 12.418,2.004 14.754,5.953 0.371,0.625 1.039,1.754 3.574,8.16 5.312,1.828 10.418,4.48 14.965,7.789 8.012,-2.953 9.32,-3.219 10.129,-3.383 l 0.738,-0.152 1.047,-0.039 c 7.012,0 12.098,7.125 13.496,9.305 3.738,5.828 3.109,10.125 1.93,12.703 -0.387,0.828 -1.137,2.441 -6.684,10.375 0.52,1.68 0.957,3.387 1.32,5.109 7.172,3.195 8.281,3.922 8.969,4.375 3.746,2.449 5.52,7.262 5.414,14.707 -0.105,7.359 -2.109,12.285 -5.953,14.648 -0.922,0.566 -2.789,1.711 -14.469,5.527 -1.621,2.895 -3.48,5.625 -5.559,8.168 1.59,5.371 1.758,6.566 1.852,7.25 0.777,5.59 -0.633,9.457 -5.035,13.785 -2.863,2.808 -6.055,4.222 -9.492,4.222 l 0,0 z" id="path3131" style="fill:#260859"/>
<path d="m 409.34,122.93 c 0,0 -5.383,-14.453 -6.75,-16.773 -1.375,-2.324 -13.246,-2.52 -14.793,0.031 -1.535,2.566 -6.75,16.742 -6.75,16.742 h 28.293 z" id="path3133" style="fill:#7f3f98"/>
<path d="m 380.41,205.176 c 0,0 -11.297,8.801 -13.367,9.836 -2.066,1.031 -3.934,1.836 -6.656,-0.824 -2.676,-2.637 -2.969,-3.941 -2.598,-6.621 0.371,-2.668 4.875,-16.578 4.875,-16.578 l 17.746,14.187 z" id="path3135" style="fill:#7f3f98"/>
<path d="m 409.645,205.176 c 0,0 11.297,8.801 13.367,9.836 2.066,1.031 3.938,1.836 6.656,-0.824 2.676,-2.637 2.969,-3.941 2.598,-6.621 -0.371,-2.668 -4.875,-16.578 -4.875,-16.578 l -17.746,14.187 z" id="path3137" style="fill:#7f3f98"/>
<path d="m 352.539,155.469 c 0,0 -14.668,6.238 -16.891,7.691 -2.211,1.449 -2.164,13.59 0.336,15.125 2.5,1.531 17.105,6.121 17.105,6.121 l -0.55,-28.937 z" id="path3139" style="fill:#7f3f98"/>
<path d="m 437.82,155.469 c 0,0 14.668,6.238 16.891,7.691 2.215,1.449 2.164,13.59 -0.336,15.125 -2.5,1.531 -17.105,6.121 -17.105,6.121 l 0.55,-28.937 z" id="path3141" style="fill:#7f3f98"/>
<path d="m 348.719,153.543 -7.418,3.023 c -0.465,4.172 0.828,11.812 6.457,16.184 5.629,4.359 0.961,-19.207 0.961,-19.207 z" id="path3143" style="fill:#260859"/>
<path d="m 441.246,153.543 7.418,3.023 c 0.465,4.172 -0.828,11.812 -6.457,16.184 -5.629,4.359 -0.961,-19.207 -0.961,-19.207 z" id="path3145" style="fill:#260859"/>
<path d="m 367.875,129.066 c 0,0 -15.164,-5.836 -17.758,-6.371 -2.598,-0.547 -9.082,7.383 -7.863,10.039 1.223,2.66 10.508,15.508 10.508,15.508 l 15.113,-19.176 z" id="path3147" style="fill:#7f3f98"/>
<path d="m 422.438,129.066 c 0,0 15.164,-5.836 17.754,-6.371 2.598,-0.547 9.086,7.383 7.867,10.039 -1.223,2.66 -10.508,15.508 -10.508,15.508 l -15.113,-19.176 z" id="path3149" style="fill:#7f3f98"/>
<path d="m 359.793,121.949 c -2.27,3.754 -6.828,9.09 -3.359,17.332 2.875,-3.961 11.133,-15.062 11.43,-16.781 l -8.071,-0.551 z" id="path3151" style="fill:#260859"/>
<path d="m 423.164,198.848 10.629,-4.398 3.391,4.844 c -4.156,3.188 -7.762,6.547 -14.637,6.121 -8.692,-0.552 0.617,-6.567 0.617,-6.567 z" id="path3153" style="fill:#260859"/>
<path d="m 366.891,198.848 -10.629,-4.398 -3.391,4.844 c 4.156,3.188 7.762,6.547 14.637,6.121 8.695,-0.552 -0.617,-6.567 -0.617,-6.567 z" id="path3155" style="fill:#260859"/>
<path d="m 430.566,121.949 c 2.266,3.754 6.824,9.09 3.352,17.332 -2.867,-3.961 -11.133,-15.062 -11.43,-16.781 l 8.078,-0.551 z" id="path3157" style="fill:#260859"/>
<path d="m 443.168,163.367 c 0,26.504 -21.488,47.984 -47.988,47.984 -26.508,0 -47.992,-21.48 -47.992,-47.984 0,-26.504 21.484,-47.996 47.992,-47.996 26.5,0 47.988,21.492 47.988,47.996 z" id="path3159" style="fill:#7f3f98"/>
</g>
<path d="m 499.035,379.352 c -24.148,-14.574 -50.754,-40.875 -46.246,-67.043 1.824,-10.57 -6.406,-19.781 -14.363,-28.688 -3.098,-3.477 -6.305,-7.066 -8.812,-10.648 -5.574,-7.969 -11.219,-18.809 -6.41,-25.188 1.828,-2.426 5.477,-3.598 11.152,-3.598 6.438,0 14.301,1.52 19.57,2.734 -2.094,-5.496 -3.824,-12.004 -1.652,-15.984 0.93,-1.707 2.5,-2.793 4.531,-3.148 0.484,-0.082 1,-0.121 1.535,-0.121 10.691,0 31.27,18.254 44.082,30.727 l 2.691,-13.578 1.098,2.488 c 0.855,0.215 21,5.586 31.73,37.02 15.328,14.332 30.715,37.719 28.375,60.863 l -1.391,13.645 -24.707,-4.203 -10.504,-1.258 10.469,12.742 -6.188,10.285 -10.91,2.156 c -4.785,0.953 -10.098,1.809 -15.793,2.543 l -4.441,0.562 -3.816,-2.308 z" id="path3161" style="fill:#260859"/>
<path d="m 499.883,380.711 c -8.453,-18.031 -15.75,-33.605 -11.617,-49.598 5.477,-21.191 4.926,-37.324 -1.633,-47.938 -5.246,-8.492 -12.496,-10.414 -13.895,-10.715 l -2.395,-0.512 -14.07,3.293 -0.402,0.141 c -17.102,5.828 -29.754,33.488 -21.32,69.688 2.219,9.543 5.305,16.332 8.051,22.375 2.02,4.445 3.656,8.047 4.535,11.91 -21.969,18.406 -37.598,42.656 -42.953,66.711 -2.16,9.668 -3.797,24.91 -4.496,41.824 l -0.195,4.844 c 48.699,-18.664 89.555,-41.785 113.125,-62.766 0.469,-12.918 -2.551,-27.004 -8.867,-40.922 -1.278,-2.812 -2.579,-5.585 -3.868,-8.335 z" id="path3163" style="fill:#260859"/>
<path d="m 506.766,421.48 c -5.457,0 -10.125,-2.191 -13.5,-6.348 -7.531,-9.25 -5.598,-25.848 -2.543,-41.09 -0.52,-0.402 -1.082,-0.809 -1.566,-1.16 -2.887,-2.09 -6.832,-4.945 -8.84,-9.621 l -3.844,-8.93 8.52,-4.684 c 26.812,-14.766 36.797,-42.465 29.68,-82.332 -0.055,-0.164 -0.105,-0.328 -0.164,-0.488 -2.809,-3.723 -6.871,-11.012 -10.637,-24.828 -3.523,-12.914 -12.309,-71.832 -7.859,-80.129 0.945,-1.77 3.852,-5.887 10.324,-5.887 4.68,0 18.578,3.645 26.375,12.609 0.766,-0.152 1.562,-0.227 2.363,-0.227 4.25,0 7.562,2.121 11.398,4.578 1.246,0.789 2.582,1.645 4.094,2.543 2.199,1.305 6.66,3.945 10.301,10.102 5.594,0.066 9.668,3.734 19.703,14.016 0.09,0.102 1.055,1.09 1.293,1.32 2.059,2.035 3.676,4.914 5.316,9.516 10.035,2.156 17.312,18.496 18.711,25.281 0.051,0.262 0.152,0.633 0.289,1.145 l 0.273,1.02 c 15.062,57.008 11.363,104.316 -10.707,136.801 -17.801,26.219 -46.922,41.906 -86.551,46.645 -0.859,0.102 -1.648,0.148 -2.429,0.148 l 0,0 z" id="path3165" style="fill:#260859"/>
<path d="m 595.402,237.887 c -1.785,-8.676 -10.664,-20.074 -11.051,-16.191 -0.199,2.031 1.609,13.535 2.16,20.777 -0.961,-0.691 -2.066,-1.449 -2.703,-1.969 -2.98,-14.074 -6.547,-29.066 -9.473,-31.961 -2.211,-2.176 -14.605,-15.398 -13.977,-11.551 2.879,17.59 7.48,30.176 11.324,39.035 -3.078,-2.262 -4.473,-3.328 -6.055,-4.422 -6.062,-4.195 -8.738,-30.359 -13.359,-39.422 -2.363,-4.652 -5.629,-6.57 -7.172,-7.484 -9.922,-5.895 -12.629,-9.863 -10.863,2.387 1.348,9.336 2.344,21.816 14.742,47.855 l -8.207,-6.227 c -6.785,-5.465 -11.07,-36.008 -13.523,-48.082 -2.031,-10.043 -21.027,-15.141 -21.797,-13.699 -1.18,2.203 3.742,53.883 8.754,72.25 5.008,18.359 10.426,24.254 10.836,25.301 3.816,20.711 5.387,47.844 -8.359,70.012 -2.25,3.625 -31.09,-18.539 -34.219,-15.227 -3.129,3.312 19.469,32.105 15.348,34.992 -2.375,1.672 -4.922,3.262 -7.656,4.766 1.898,4.414 10.406,6.801 11.91,12.598 0.566,0 -11.004,41.09 5.863,39.07 136.755,-16.336 89.27,-164.133 87.477,-172.808 z" id="path3167" style="fill:#ffffff"/>
<path d="m 519.477,379.414 c -7.062,-21.422 -20.711,-50.16 -20.711,-50.16 l -28.637,-11.207 19.031,63.051 -6.086,-5.641 -1.121,4.543 10.562,19.551 c 0,0 27.895,4.254 31.422,-6.102 -1.546,-5.48 -2.132,-6.969 -4.46,-14.035 z" id="path3169" style="fill:#aaa4c4"/>
<path d="m 506.004,389.176 c -3.055,0.156 -3.531,-6.988 -5.977,-6.602 -1.98,12.016 -3.234,29.453 7.898,28.121 105.012,-12.539 101.387,-102.594 93.238,-147.656 -1.339,28.816 1.314,121.039 -95.159,126.137 z" id="path3171" style="fill:#aaa4c4"/>
<path d="m 499.363,403.242 c 1.051,4.82 3.543,8.055 8.562,7.453 48.184,-5.754 73.453,-27.84 85.957,-54.395 -20.577,34.462 -64.964,42.055 -94.519,46.942 z" id="path3173" style="fill:#f2f1f8"/>
<path d="m 536.113,285.504 c -10.438,-31.156 -30.414,-36.156 -30.414,-36.156 l -1.723,13.531 c -1.992,-1.926 -34.645,-35.117 -46.812,-33.012 -8.293,1.434 -0.457,18.242 0.266,20.086 -6.105,-1.598 -28.066,-6.832 -32.543,-0.898 -4.473,5.93 2.891,17.617 6.457,22.711 8.84,12.648 26.277,24.93 23.523,40.898 -4.41,25.586 22.328,51.047 45.258,64.883 l 3.191,1.93 3.703,-0.469 c 5.539,-0.715 10.805,-1.555 15.66,-2.52 l 9.992,-1.977 4.938,-8.211 -12.848,-15.648 15.812,1.898 22.48,3.824 1.168,-11.398 c 2.088,-20.64 -11.045,-43.691 -28.108,-59.472 z" id="path3175" style="fill:#260859"/>
<path d="m 511.441,262.371 0.492,25.715 20.984,8.66 C 522.91,277.422 511.441,262.371 511.441,262.371 z" id="path3177" style="fill:#6b5f91"/>
<path d="m 497.977,381.613 c -8.625,-18.406 -16.074,-34.297 -11.754,-51.027 5.328,-20.621 4.859,-36.199 -1.383,-46.305 -4.797,-7.758 -11.289,-9.492 -12.543,-9.758 l -1.934,-0.414 -13.398,3.125 -0.414,0.145 c -16.215,5.523 -28.109,32.18 -19.945,67.215 2.172,9.352 5.219,16.047 7.902,21.953 2.297,5.055 4.102,9.027 4.949,13.617 -21.887,18.016 -37.902,42.508 -43.219,66.363 -2.129,9.539 -3.754,24.648 -4.445,41.449 l -0.16,3.938 c 46.297,-17.949 85.312,-39.887 108.82,-60.047 0.855,-12.961 -2.055,-27.484 -8.621,-41.949 -1.273,-2.801 -2.57,-5.566 -3.855,-8.305 z" id="path3179" style="fill:#260859"/>
<path d="m 414.879,448.457 c -1.84,8.227 -3.52,22.379 -4.238,39.879 36.367,-14.809 67.703,-31.938 89.738,-48.418 3.441,-14 0.355,-31.008 -6.609,-46.34 -10.18,-22.418 -21.957,-42.605 -16.117,-65.207 10.691,-41.363 -7.207,-45.191 -7.207,-45.191 l -11.039,2.574 c -11.812,4.027 -21.172,26.828 -14.184,56.836 4.383,18.836 12.867,26.305 13.566,41.469 -24.969,19.054 -39.453,44.386 -43.91,64.398 z" id="path3181" style="fill:#ffffff"/>
<polygon points="524.949,339.023 553.559,343.895 540.949,327.73 497.863,316.172 478.828,322.18 505.211,341.258 515.43,341.129 518.512,346.129 " id="polygon3183" style="fill:#42316f"/>
<path d="m 512.535,370.281 c -0.336,-0.113 -1.629,-0.211 -2.324,-0.262 -3.934,-0.297 -11.246,-0.84 -16.621,-8.176 -9.293,-12.676 -18.852,-30.539 -18.945,-30.719 l -1.918,-3.586 16.203,-15.387 3.598,2.605 c 10.914,7.887 31.23,22.578 27.18,51.25 l -0.93,6.586 -6.243,-2.311 z" id="path3185" style="fill:#260859"/>
<path d="m 507.996,273.875 c -8.719,-4.91 -1.633,8.113 -1.633,8.113 l 17.391,8.082 c 0,0 -7.035,-11.285 -15.758,-16.195 z" id="path3187" style="fill:#260859"/>
<path d="m 497.902,358.684 c 5.445,7.418 12.918,5.246 16.504,6.578 3.41,-24.145 -12.492,-37.109 -25.016,-46.168 l -10.02,9.52 c 10e-4,-10e-4 9.341,17.515 18.532,30.07 z" id="path3189" style="fill:#f6a0a6"/>
<polygon points="494.504,330.309 504.152,329.352 500.211,320.141 490.449,320.98 " id="polygon3191" style="fill:#260859"/>
<path d="m 477.652,328.371 c 0.344,-1.586 0.645,-3.094 0.914,-4.574 l -0.824,-32.625 -7.129,-5.695 -4.527,-1.277 -6.68,1.555 c -3.07,1.051 -5.98,3.387 -8.48,6.777 4.602,7.199 9.676,10.191 8.43,22.199 -1.32,12.793 10.867,25.336 16.84,28.691 -0.165,-4.742 0.284,-9.649 1.456,-15.051 z" id="path3193" style="fill:#aaa4c4"/>
<path d="m 515.441,362.789 c 2.875,-0.449 5.562,-0.922 8.031,-1.41 -11.984,-10.055 -24.457,-25.418 -30.348,-40.766 1.129,-0.16 2.285,-0.285 3.461,-0.387 l -12.074,-9.066 -1.441,17.137 20.973,26.426 11.398,8.066 z" id="path3195" style="fill:#260859"/>
<g id="g3197">
<path d="m 520.594,365.984 c -11.988,-10.059 -24.457,-25.414 -30.348,-40.773 14.125,-2 31.789,-0.09 63.312,18.684 2.402,-23.664 -8.188,-64.223 -120.211,-88.75 19.531,31.617 35.305,33.953 32.133,58.875 -2.477,19.504 17.742,40.82 40.18,54.359 5.613,-0.715 10.582,-1.535 14.934,-2.395 z" id="path3199" style="fill:#ffffff"/>
</g>
<polygon points="502.367,321.293 514.109,336.367 528.445,325.293 " id="polygon3201" style="fill:#ffffff"/>
<polygon points="474.906,256.566 459.891,260.328 490.523,302.746 " id="polygon3203" style="fill:#260859"/>
<polygon points="519.023,350.121 506.781,357.129 514.066,363.012 " id="polygon3205" style="fill:#ffffff"/>
<polygon points="515.023,361.746 520.594,365.984 523.348,358.102 " id="polygon3207" style="fill:#ffffff"/>
<g id="g3209">
<path d="m 462.426,239.809 c 11.012,28.695 21.609,50.254 24.316,56.68 3.309,7.875 6.352,11.246 16.789,16.836 6.863,3.676 19.824,10.402 31.555,10.422 -8.766,-21.824 -16.195,-32.91 -38.211,-53.188 -11.328,-10.43 -24.145,-21.758 -34.449,-30.75 z" id="path3211" style="fill:#594c82"/>
</g>
<g id="g3213">
<path d="M 521.926,322.051 C 505.781,318.36 496.391,306.5 495.473,288.668 l -0.387,-7.441 6.039,4.363 c 20.16,14.57 24.406,26.645 25.137,32.543 l 0.633,5.062 -4.969,-1.144 z" id="path3215" style="fill:#260859"/>
</g>
<g id="g3217">
<path d="m 504.73,294.418 c 0.742,14.297 7.789,26.453 23.688,30.094 -0.844,-6.774 -6.383,-17.582 -23.688,-30.094 z" id="path3219" style="fill:#ffffff"/>
</g>
<path d="m 521.02,307.242 -1.926,-0.84 c -0.336,0.574 -0.645,1.184 -0.918,1.844 -1.785,4.355 -1.414,8.625 0.836,9.559 1.629,0.664 3.961,-0.762 5.711,-3.18 l -3.703,-7.383 z" id="path3221" style="fill:#260859"/>
<path d="m 493.77,393.578 c -0.039,-0.094 -0.086,-0.184 -0.125,-0.273 -1.496,2.672 -2.945,5.547 -2.945,5.547 0,0 -19.02,-6.207 -25.148,-7.895 -5.867,10.895 -20.238,38.785 -8.461,75.781 16.672,-8.82 31.375,-17.91 43.289,-26.82 3.44,-14 0.354,-31.008 -6.61,-46.34 z" id="path3223" style="fill:#6b5f91"/>
<path d="m 282.871,437.34 c 22.973,18.836 59.043,39.004 101.59,55.91 v -12.582 c -45.699,-18.512 -81.504,-40.121 -101.59,-58.043 v 14.715 z" id="path3225" style="fill:#260859"/>
<path d="m 406.188,493.156 c 42.293,-16.809 78.164,-36.848 101.102,-55.594 v -14.703 c -19.926,17.703 -55.094,38.953 -99.949,57.25 l -1.153,13.047 z" id="path3227" style="fill:#260859"/>
<path d="m 403.402,148.789 c -0.047,-0.816 0.004,-1.645 0.133,-2.477 1.031,-5.996 6.719,-10.016 12.719,-8.984 5.887,1.008 9.855,6.508 9.039,12.367 -7.613,-1.144 -14.949,-1.629 -21.891,-0.906 z" id="path3229" style="fill:#ffffff"/>
<path d="m 365.43,162.512 c 6.816,9.141 17.707,15.051 29.973,15.051 12.27,0 23.16,-5.91 29.973,-15.051 H 365.43 z" id="path3231" style="fill:#260859"/>
<path d="m 416.684,170.902 c -4.809,-1.645 -12.762,-2.707 -21.766,-2.707 -8.594,0 -16.242,0.969 -21.102,2.484 6.102,4.32 13.543,6.883 21.586,6.883 7.907,0 15.239,-2.472 21.282,-6.66 z" id="path3233" style="fill:#b30838"/>
<path d="m 359.141,162.512 0.438,1.328 c 3.145,9.539 4.848,12.016 8.293,12.043 h 0.027 c 3.363,0 5.168,-2.57 8.371,-11.938 l 0.496,-1.434 h -17.625 z" id="path3235" style="fill:#260859"/>
<g id="g3237">
<path d="m 363.828,162.43 c 0,0 2.953,8.965 4.055,8.973 1.102,0.012 4.156,-8.914 4.156,-8.914 l -8.211,-0.059 z" id="path3239" style="fill:#ffffff"/>
</g>
<path d="m 414.266,162.512 0.438,1.328 c 3.145,9.539 4.848,12.016 8.293,12.043 h 0.027 c 3.363,0 5.168,-2.57 8.375,-11.938 l 0.492,-1.434 h -17.625 z" id="path3241" style="fill:#260859"/>
<g id="g3243">
<path d="m 418.953,162.43 c 0,0 2.953,8.965 4.055,8.973 1.105,0.012 4.156,-8.914 4.156,-8.914 l -8.211,-0.059 z" id="path3245" style="fill:#ffffff"/>
</g>
<path d="m 411.148,196.828 c 0,4.668 -7.133,8.449 -15.926,8.449 -8.797,0 -15.93,-3.781 -15.93,-8.449 0,-4.668 7.133,-8.449 15.93,-8.449 8.794,0 15.926,3.781 15.926,8.449 z" id="path3247" style="fill:#ffef6f"/>
<path d="m 400.66,196.828 c 0,1.594 -2.434,2.883 -5.438,2.883 -3,0 -5.438,-1.289 -5.438,-2.883 0,-1.598 2.438,-2.891 5.438,-2.891 3.005,10e-4 5.438,1.293 5.438,2.891 z" id="path3249" style="fill:#7f3f98"/>
<path d="m 410.676,141.695 c 0.078,2.168 1.301,3.871 2.711,3.816 1.422,-0.066 2.496,-1.863 2.402,-4.031 -0.082,-2.176 -1.309,-3.895 -2.727,-3.832 -1.414,0.059 -2.492,1.868 -2.386,4.047 z" id="path3251" style="fill:#260859"/>
<path d="m 386.906,148.789 c 0.051,-0.816 -0.004,-1.645 -0.133,-2.477 -1.027,-5.996 -6.715,-10.016 -12.715,-8.984 -5.887,1.008 -9.855,6.508 -9.039,12.367 7.614,-1.144 14.95,-1.629 21.887,-0.906 z" id="path3253" style="fill:#ffffff"/>
<path d="m 379.633,141.695 c -0.082,2.168 -1.301,3.871 -2.707,3.816 -1.426,-0.066 -2.504,-1.863 -2.402,-4.031 0.082,-2.176 1.309,-3.895 2.723,-3.832 1.417,0.059 2.495,1.868 2.386,4.047 z" id="path3255" style="fill:#260859"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 39 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 30 KiB

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

@@ -6,14 +6,14 @@
"request": "launch",
"type": "dart",
"flutterMode": "debug",
"program": "mobile/apps/auth/lib/main.dart",
"program": "auth/lib/main.dart",
"args": ["--dart-define", "endpoint=http://localhost:8080"]
},
{
"name": "Auth Android Dev",
"request": "launch",
"type": "dart",
"program": "mobile/apps/auth/lib/main.dart",
"program": "auth/lib/main.dart",
"args": [
"--dart-define",
"endpoint=http://192.168.1.3:8080",
@@ -25,21 +25,21 @@
"name": "Auth iOS Dev",
"request": "launch",
"type": "dart",
"program": "mobile/apps/auth/lib/main.dart",
"program": "auth/lib/main.dart",
"args": ["--dart-define", "endpoint=http://192.168.1.30:8080"]
},
{
"name": "Auth iOS Prod",
"request": "launch",
"type": "dart",
"program": "mobile/apps/auth/lib/main.dart",
"program": "auth/lib/main.dart",
"args": ["--target", "lib/main.dart"]
},
{
"name": "Auth Android Prod",
"request": "launch",
"type": "dart",
"program": "mobile/apps/auth/lib/main.dart",
"program": "auth/lib/main.dart",
"args": ["--target", "lib/main.dart", "--flavor", "independent"]
}
]

View File

@@ -1,51 +1,31 @@
Ente Auth is the best and the only 2FA authenticator app you will ever need. It provides secure, end-to-end encrypted backup to your codes, works across devices whether its Android, iOS, Mac, Windows, Linux or Web. It also offers quality of life features like Tap to Copy, Next Code, and even allows you to share your codes securely with others.
ente's Authenticator app helps you generate and store 2 step verification (2FA) tokens on your mobile devices.
Our customers absolutely love it.
- It works everywhere and can either be used in the cloud with end-to-end encryption or on a single device without the need for an account. Entes UI is well thought out and easy to use. Plus it even shows you the next code if the current one is about to expire so you dont have to wait for it to roll over before your start typing. You can even pin, tag, and search your codes which makes it a lot easier to manage a big list compared to Google Authenticator. They call it a labour of love on their Github page, and it really looks like one. - Linus Tech Tips
FEATURES
- Underrated but great authenticator app. Free, open source, and offers cloud backup. Very stable, has nice QoL features like the preview for the next code and the search bar. Overall, the best 2FA app I've used yet. - Luna Lometta
- Secure Backups
ente provides end-to-end encrypted cloud backups so that you don't have to worry about losing your tokens. We use the same protocols Ente Photos uses to encrypt and preserve your data.
- Fantastic, fluid, has a dark theme, is open source, and also has a PC program. I switched from Authy to Ente Auth precisely for this reason, and I was surprised since the app as a whole is better and faster. - Daniel Ramos
- Multi Device Synchronization
ente will automatically sync the 2FA tokens you add to your account, across all your devices. Every new device you sign into will have access to these tokens.
- Better than Google Authenticator. - Piaw Piaw Kittens
- Web access
You can access your 2FA code from any web browser by visiting https://auth.ente.io .
- Authy's best replacement. Open source, desktop support, synchronization, convenient token export. Huge thanks to the developers, I hope your product will become popular and famous. - Sergey Tverye
- Offline Mode
ente generates 2FA tokens offline, so your network connectivity will not get in the way of your workflow.
- By far my favourite 2FA app. Over the years I've moved from Google Authenticator to Authy and have now happily "settled" with Ente Auth. - Dan Walsh
- Import and Export Tokens
You can add tokens to ente by one of the following methods:
1. Scanning a QR code
2. Manually entering (copy-pasting) a 2FA secret
3. Bulk importing from a file that contains a list of codes in the following format:
- The best MFA app I ever used. I will never go back to Google Authenticator. - Pierre-Philippe Lessard
otpauth://totp/provider.com:you@email.com?secret=YOUR_SECRET
Ente Auth is recommended by Linus Tech Tips, CERN, Zerodha and many others.
The codes maybe separated by new lines or commas.
✨ Features
EASY IMPORT
Add TOTP 2FA Codes to Ente Auth easily. You can either scan a QR code, or import from other authenticator apps to make sure you never lose a code while migrating
CROSS PLATFORM
Ente Auth is available cross platform and supports all major devices and OS - including Android, iOS, Mac, Windows, Linux and Web.
SECURE E2EE BACKUP
Ente Auth provides end-to-end encrypted cloud backups so that you don't have to worry about losing your tokens. We use the same protocols Ente Photos uses to encrypt and preserve your data.
OFFLINE MODE - NO SIGNUP REQUIRED
Ente Auth generates 2FA tokens offline, so your network connectivity will not get in the way of your workflow. You can even use Ente Auth without signing up for backups and use it locally for as long as you want
INTUITIVE SEARCH
Ente Auth allows you to find your 2FA codes through one tap search. No more scrolling through a long list to find the right codes. Just tap on search and start typing.
CUSTOMISE YOUR EXPERIENCE
Customise your experience of Ente Auth to make it like you want. Reorder your 2FA codes so that your most frequently used services are always on top. Change the icons by choosing from our massive icon library. Add tags so that you can filter codes like you want
SEE NEXT CODE
Ever had to pause for the timer to run out on the current code, so you can type in the new 2FA code? Ente Auth makes your workflow extremely fast by displaying the next code prominently. Say goodbye to waiting
SHARE 2FA CODE
We all have sent multiple messages to that colleague who keeps asking for the 2FA code to a shared account. Such a waste of productive time. With Ente Auth, you can securely share your 2FA tokens as a link. You can even set an expiry time for the link as well.
ADD NOTES
Use notes to save any additional information including recovery codes. All notes are backed up with end to end encryption so you dont have to worry about losing them.
You can also export the codes you have added to ente, to an **unencrypted** text file, that adheres to the above format.
SUPPORT

View File

@@ -1,81 +0,0 @@
<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_41060_128753)">
<rect width="1024" height="1024" rx="234" fill="url(#paint0_linear_41060_128753)"/>
<g opacity="0.8" filter="url(#filter0_dii_41060_128753)">
<path d="M512.364 162L226 289.273V480.182C226 656.773 348.182 821.909 512.364 862C676.545 821.909 798.727 656.773 798.727 480.182V289.273L512.364 162ZM512.364 352.909C556.909 352.909 601.455 387.909 601.455 432.455V480.182C620.546 480.182 639.636 499.273 639.636 521.545V632.909C639.636 652 620.545 671.091 598.273 671.091H423.273C404.182 671.091 385.091 652 385.091 629.727V518.364C385.091 499.273 404.182 480.182 423.273 480.182V432.455C423.273 387.909 467.818 352.909 512.364 352.909ZM512.364 391.091C486.909 391.091 464.636 407 464.636 432.455V480.182H560.091V432.455C560.091 407 537.818 391.091 512.364 391.091Z" fill="white"/>
</g>
<g opacity="0.8" filter="url(#filter1_dii_41060_128753)">
<path d="M512.364 162L226 289.273V480.182C226 656.773 348.182 821.909 512.364 862C676.545 821.909 798.727 656.773 798.727 480.182V289.273L512.364 162ZM512.364 352.909C556.909 352.909 601.455 387.909 601.455 432.455V480.182C620.546 480.182 639.636 499.273 639.636 521.545V632.909C639.636 652 620.545 671.091 598.273 671.091H423.273C404.182 671.091 385.091 652 385.091 629.727V518.364C385.091 499.273 404.182 480.182 423.273 480.182V432.455C423.273 387.909 467.818 352.909 512.364 352.909ZM512.364 391.091C486.909 391.091 464.636 407 464.636 432.455V480.182H560.091V432.455C560.091 407 537.818 391.091 512.364 391.091Z" fill="white"/>
</g>
<g opacity="0.8" filter="url(#filter2_ii_41060_128753)">
<path d="M512.364 162L226 289.273V480.182C226 656.773 348.182 821.909 512.364 862C676.545 821.909 798.727 656.773 798.727 480.182V289.273L512.364 162ZM512.364 352.909C556.909 352.909 601.455 387.909 601.455 432.455V480.182C620.546 480.182 639.636 499.273 639.636 521.545V632.909C639.636 652 620.545 671.091 598.273 671.091H423.273C404.182 671.091 385.091 652 385.091 629.727V518.364C385.091 499.273 404.182 480.182 423.273 480.182V432.455C423.273 387.909 467.818 352.909 512.364 352.909ZM512.364 391.091C486.909 391.091 464.636 407 464.636 432.455V480.182H560.091V432.455C560.091 407 537.818 391.091 512.364 391.091Z" fill="white"/>
</g>
</g>
<defs>
<filter id="filter0_dii_41060_128753" x="46.613" y="90.2452" width="931.502" height="1058.77" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="107.632"/>
<feGaussianBlur stdDeviation="89.6935"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.35 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_41060_128753"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_41060_128753" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="17.9387"/>
<feGaussianBlur stdDeviation="8.96935"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="shape" result="effect2_innerShadow_41060_128753"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-8.96935"/>
<feGaussianBlur stdDeviation="4.48467"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="effect2_innerShadow_41060_128753" result="effect3_innerShadow_41060_128753"/>
</filter>
<filter id="filter1_dii_41060_128753" x="46.613" y="90.2452" width="931.502" height="1058.77" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="107.632"/>
<feGaussianBlur stdDeviation="89.6935"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.12 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_41060_128753"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_41060_128753" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="17.9387"/>
<feGaussianBlur stdDeviation="8.96935"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="shape" result="effect2_innerShadow_41060_128753"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-8.96935"/>
<feGaussianBlur stdDeviation="4.48467"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="effect2_innerShadow_41060_128753" result="effect3_innerShadow_41060_128753"/>
</filter>
<filter id="filter2_ii_41060_128753" x="226" y="153.031" width="572.728" height="726.908" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="17.9387"/>
<feGaussianBlur stdDeviation="8.96935"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_41060_128753"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-8.96935"/>
<feGaussianBlur stdDeviation="4.48467"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="effect1_innerShadow_41060_128753" result="effect2_innerShadow_41060_128753"/>
</filter>
<linearGradient id="paint0_linear_41060_128753" x1="96.5" y1="71" x2="985" y2="977.5" gradientUnits="userSpaceOnUse">
<stop stop-color="#C373F2"/>
<stop offset="1" stop-color="#9610D6"/>
</linearGradient>
<clipPath id="clip0_41060_128753">
<rect width="1024" height="1024" rx="234" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 810 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 828 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 825 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 950 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 760 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 811 KiB

View File

@@ -1 +1 @@
Free, Cross Platform, Private, Open Source Two Factor Authenticator App
ente is an end-to-end encrypted authenticator app

View File

@@ -1 +1 @@
Ente Auth - 2FA Authenticator
Ente Authenticator

View File

@@ -1,32 +0,0 @@
#
# Generated file, do not edit.
#
import lldb
def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_dict):
"""Intercept NOTIFY_DEBUGGER_ABOUT_RX_PAGES and touch the pages."""
base = frame.register["x0"].GetValueAsAddress()
page_len = frame.register["x1"].GetValueAsUnsigned()
# Note: NOTIFY_DEBUGGER_ABOUT_RX_PAGES will check contents of the
# first page to see if handled it correctly. This makes diagnosing
# misconfiguration (e.g. missing breakpoint) easier.
data = bytearray(page_len)
data[0:8] = b'IHELPED!'
error = lldb.SBError()
frame.GetThread().GetProcess().WriteMemory(base, data, error)
if not error.Success():
print(f'Failed to write into {base}[+{page_len}]', error)
return
def __lldb_init_module(debugger: lldb.SBDebugger, _):
target = debugger.GetDummyTarget()
# Caveat: must use BreakpointCreateByRegEx here and not
# BreakpointCreateByName. For some reasons callback function does not
# get carried over from dummy target for the later.
bp = target.BreakpointCreateByRegex("^NOTIFY_DEBUGGER_ABOUT_RX_PAGES$")
bp.SetScriptCallbackFunction('{}.handle_new_rx_page'.format(__name__))
bp.SetAutoContinue(True)
print("-- LLDB integration loaded --")

View File

@@ -1,5 +0,0 @@
#
# Generated file, do not edit.
#
command script import --relative-to-command-file flutter_lldb_helper.py

View File

@@ -3,6 +3,7 @@ PODS:
- Flutter
- connectivity_plus (0.0.1):
- Flutter
- FlutterMacOS
- cupertino_http (0.0.1):
- Flutter
- FlutterMacOS
@@ -39,8 +40,6 @@ PODS:
- DKPhotoGallery/Resource (0.0.19):
- SDWebImage
- SwiftyGif
- ente_qr (0.0.1):
- Flutter
- file_picker (0.0.1):
- DKImagePickerController/PhotoGallery
- Flutter
@@ -62,12 +61,13 @@ PODS:
- Flutter
- flutter_local_notifications (0.0.1):
- Flutter
- flutter_native_splash (2.4.3):
- flutter_native_splash (0.0.1):
- Flutter
- flutter_secure_storage (6.0.0):
- Flutter
- fluttertoast (0.0.2):
- Flutter
- Toast
- local_auth_darwin (0.0.1):
- Flutter
- FlutterMacOS
@@ -102,43 +102,37 @@ PODS:
- FlutterMacOS
- sodium_libs (2.2.1):
- Flutter
- sqflite_darwin (0.0.4):
- sqflite (0.0.3):
- Flutter
- FlutterMacOS
- sqlite3 (3.50.2):
- sqlite3/common (= 3.50.2)
- sqlite3/common (3.50.2)
- sqlite3/dbstatvtab (3.50.2):
- "sqlite3 (3.46.1+1)":
- "sqlite3/common (= 3.46.1+1)"
- "sqlite3/common (3.46.1+1)"
- "sqlite3/dbstatvtab (3.46.1+1)":
- sqlite3/common
- sqlite3/fts5 (3.50.2):
- "sqlite3/fts5 (3.46.1+1)":
- sqlite3/common
- sqlite3/math (3.50.2):
- "sqlite3/perf-threadsafe (3.46.1+1)":
- sqlite3/common
- sqlite3/perf-threadsafe (3.50.2):
- sqlite3/common
- sqlite3/rtree (3.50.2):
- "sqlite3/rtree (3.46.1+1)":
- sqlite3/common
- sqlite3_flutter_libs (0.0.1):
- Flutter
- FlutterMacOS
- sqlite3 (~> 3.50.1)
- "sqlite3 (~> 3.46.0+1)"
- sqlite3/dbstatvtab
- sqlite3/fts5
- sqlite3/math
- sqlite3/perf-threadsafe
- sqlite3/rtree
- SwiftyGif (5.4.5)
- ua_client_hints (1.4.1):
- Flutter
- Toast (4.1.1)
- url_launcher_ios (0.0.1):
- Flutter
DEPENDENCIES:
- app_links (from `.symlinks/plugins/app_links/ios`)
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`)
- 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`)
@@ -161,9 +155,8 @@ DEPENDENCIES:
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- 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`)
- sqflite (from `.symlinks/plugins/sqflite/darwin`)
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
SPEC REPOS:
@@ -176,18 +169,17 @@ SPEC REPOS:
- Sentry
- sqlite3
- SwiftyGif
- Toast
EXTERNAL SOURCES:
app_links:
:path: ".symlinks/plugins/app_links/ios"
connectivity_plus:
:path: ".symlinks/plugins/connectivity_plus/ios"
:path: ".symlinks/plugins/connectivity_plus/darwin"
cupertino_http:
: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:
@@ -232,54 +224,51 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
sodium_libs:
:path: ".symlinks/plugins/sodium_libs/ios"
sqflite_darwin:
:path: ".symlinks/plugins/sqflite_darwin/darwin"
sqflite:
:path: ".symlinks/plugins/sqflite/darwin"
sqlite3_flutter_libs:
:path: ".symlinks/plugins/sqlite3_flutter_libs/darwin"
ua_client_hints:
:path: ".symlinks/plugins/ua_client_hints/ios"
:path: ".symlinks/plugins/sqlite3_flutter_libs/ios"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
SPEC CHECKSUMS:
app_links: f3e17e4ee5e357b39d8b95290a9b2c299fca71c6
connectivity_plus: 2a701ffec2c0ae28a48cf7540e279787e77c447d
app_links: e7a6750a915a9e161c58d91bc610e8cd1d4d0ad0
connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db
cupertino_http: 947a233f40cfea55167a49f2facc18434ea117ba
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
ente_qr: f39434aa69ea0e71047b49316365b2737f8a20aa
file_picker: b159e0c068aef54932bb15dc9fd1571818edaf49
file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655
file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808
fk_user_agent: 1f47ec39291e8372b1d692b50084b0d54103c545
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_email_sender: e03bdda7637bcd3539bfe718fddd980e9508efaa
flutter_email_sender: 10a22605f92809a11ef52b2f412db806c6082d40
flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4
flutter_local_authentication: 1172a4dd88f6306dadce067454e2c4caf07977bb
flutter_local_notifications: df98d66e515e1ca797af436137b4459b160ad8c9
flutter_native_splash: df59bb2e1421aa0282cb2e95618af4dcb0c56c29
flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086
flutter_native_splash: edf599c81f74d093a4daf8e17bd7a018854bc778
flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12
fluttertoast: 21eecd6935e7064cc1fcb733a4c5a428f3f24f0f
local_auth_darwin: fa4b06454df7df8e97c18d7ee55151c57e7af0de
fluttertoast: e9a18c7be5413da53898f660530c56f35edfba9c
local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3
move_to_background: 39a5b79b26d577b0372cbe8a8c55e7aa9fcd3a2d
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
objective_c: 77e887b5ba1827970907e10e832eec1683f3431d
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
privacy_screen: 1a131c052ceb3c3659934b003b0d397c2381a24e
qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e
SDWebImage: f29024626962457f3470184232766516dee8dfea
Sentry: da60d980b197a46db0b35ea12cb8f39af48d8854
sentry_flutter: 2df8b0aab7e4aba81261c230cbea31c82a62dd1b
share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
sodium_libs: 1faae17af662384acbd13e41867a0008cd2e2318
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
sqlite3: 3e82a2daae39ba3b41ae6ee84a130494585460fc
sqlite3_flutter_libs: 2c48c4ee7217fd653251975e43412250d5bcbbe2
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
sqlite3: 0bb0e6389d824e40296f531b858a2a0b71c0d2fb
sqlite3_flutter_libs: c00457ebd31e59fa6bb830380ddba24d44fbcd3b
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
ua_client_hints: aeabd123262c087f0ce151ef96fa3ab77bfc8b38
Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
PODFILE CHECKSUM: 78f002751f1a8f65042b8da97902ba4124271c5a

View File

@@ -26,7 +26,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
@@ -44,13 +43,11 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@@ -2,21 +2,20 @@ import 'dart:async';
import 'dart:io';
import 'package:adaptive_theme/adaptive_theme.dart';
import 'package:ente_accounts/services/user_service.dart';
import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/core/event_bus.dart';
import 'package:ente_auth/ente_theme_data.dart';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/events/signed_in_event.dart';
import 'package:ente_auth/events/signed_out_event.dart';
import "package:ente_auth/l10n/l10n.dart";
import 'package:ente_auth/locale.dart';
import "package:ente_auth/onboarding/view/onboarding_page.dart";
import 'package:ente_auth/services/authenticator_service.dart';
import 'package:ente_auth/services/update_service.dart';
import 'package:ente_auth/services/user_service.dart';
import 'package:ente_auth/services/window_listener_service.dart';
import 'package:ente_auth/ui/home_page.dart';
import 'package:ente_auth/ui/settings/app_update_dialog.dart';
import 'package:ente_events/event_bus.dart';
import 'package:ente_events/models/signed_in_event.dart';
import 'package:ente_events/models/signed_out_event.dart';
import 'package:ente_strings/l10n/strings_localizations.dart';
import 'package:flutter/foundation.dart';
import "package:flutter/material.dart";
import 'package:flutter_localizations/flutter_localizations.dart';
@@ -41,7 +40,7 @@ class _AppState extends State<App>
late StreamSubscription<SignedOutEvent> _signedOutEvent;
late StreamSubscription<SignedInEvent> _signedInEvent;
Locale? locale;
void setLocale(Locale newLocale) {
setLocale(Locale newLocale) {
setState(() {
locale = newLocale;
});
@@ -83,7 +82,7 @@ class _AppState extends State<App>
UpdateService.instance.getLatestVersionInfo(),
);
},
barrierColor: Colors.black.withValues(alpha: 0.85),
barrierColor: Colors.black.withOpacity(0.85),
);
});
}
@@ -132,7 +131,6 @@ class _AppState extends State<App>
localeListResolutionCallback: localResolutionCallBack,
localizationsDelegates: const [
AppLocalizations.delegate,
StringsLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
@@ -152,7 +150,6 @@ class _AppState extends State<App>
localeListResolutionCallback: localResolutionCallBack,
localizationsDelegates: const [
AppLocalizations.delegate,
StringsLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,

View File

@@ -27,8 +27,10 @@ Future<void> bootstrap(FutureOr<Widget> Function() builder) async {
await runZonedGuarded(
() async {
Bloc.observer = AppBlocObserver();
runApp(await builder());
await BlocOverrides.runZoned(
() async => runApp(await builder()),
blocObserver: AppBlocObserver(),
);
},
(error, stackTrace) => log(error.toString(), stackTrace: stackTrace),
);

View File

@@ -1,36 +1,95 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io' as io;
import 'dart:typed_data';
import 'package:ente_base/models/database.dart';
import 'package:ente_configuration/base_configuration.dart';
import 'package:bip39/bip39.dart' as bip39;
import 'package:ente_auth/core/constants.dart';
import 'package:ente_auth/core/event_bus.dart';
import 'package:ente_auth/events/endpoint_updated_event.dart';
import 'package:ente_auth/events/signed_in_event.dart';
import 'package:ente_auth/events/signed_out_event.dart';
import 'package:ente_auth/models/key_attributes.dart';
import 'package:ente_auth/models/key_gen_result.dart';
import 'package:ente_auth/models/private_key_attributes.dart';
import 'package:ente_auth/store/authenticator_db.dart';
import 'package:ente_auth/utils/directory_utils.dart';
import 'package:ente_crypto_dart/ente_crypto_dart.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:logging/logging.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
import 'package:tuple/tuple.dart';
class Configuration extends BaseConfiguration {
class Configuration {
Configuration._privateConstructor();
static final Configuration instance = Configuration._privateConstructor();
static const endpoint = String.fromEnvironment(
"endpoint",
defaultValue: kDefaultProductionEndpoint,
);
static const emailKey = "email";
static const keyAttributesKey = "key_attributes";
static const lastTempFolderClearTimeKey = "last_temp_folder_clear_time";
static const keyKey = "key";
static const secretKeyKey = "secret_key";
static const authSecretKeyKey = "auth_secret_key";
static const offlineAuthSecretKey = "offline_auth_secret_key";
static const tokenKey = "token";
static const encryptedTokenKey = "encrypted_token";
static const userIDKey = "user_id";
static const hasMigratedSecureStorageKey = "has_migrated_secure_storage";
static const hasOptedForOfflineModeKey = "has_opted_for_offline_mode";
static const endPointKey = "endpoint";
final List<String> onlineSecureKeys = [
keyKey,
secretKeyKey,
authSecretKeyKey,
];
final kTempFolderDeletionTimeBuffer = const Duration(days: 1).inMicroseconds;
static final _logger = Logger("Configuration");
String? _cachedToken;
late SharedPreferences _preferences;
String? _key;
String? _secretKey;
String? _authSecretKey;
String? _offlineAuthKey;
late FlutterSecureStorage _secureStorage;
late String _tempDirectory;
@override
Future<void> init(List<EnteBaseDatabase> dbs) async {
await super.init(dbs);
String? _volatilePassword;
Future<void> init() async {
_preferences = await SharedPreferences.getInstance();
sqfliteFfiInit();
_secureStorage = const FlutterSecureStorage(
iOptions: IOSOptions(
accessibility: KeychainAccessibility.first_unlock_this_device,
),
);
sqfliteFfiInit();
_tempDirectory = (await DirectoryUtils.getDirectoryForInit()).path;
final tempDirectory = io.Directory(_tempDirectory);
try {
final currentTime = DateTime.now().microsecondsSinceEpoch;
if (tempDirectory.existsSync() &&
(_preferences.getInt(lastTempFolderClearTimeKey) ?? 0) <
(currentTime - kTempFolderDeletionTimeBuffer)) {
await tempDirectory.delete(recursive: true);
await _preferences.setInt(lastTempFolderClearTimeKey, currentTime);
_logger.info("Cleared temp folder");
} else {
_logger.info("Skipping temp folder clear");
}
} catch (e) {
_logger.warning(e);
}
tempDirectory.createSync(recursive: true);
await _initOnlineAccount();
await _initOfflineAccount();
}
@@ -40,10 +99,303 @@ class Configuration extends BaseConfiguration {
);
}
@override
Future<void> _initOnlineAccount() async {
if (!_preferences.containsKey(tokenKey)) {
for (final key in onlineSecureKeys) {
unawaited(
_secureStorage.delete(
key: key,
),
);
}
} else {
_key = await _secureStorage.read(
key: keyKey,
);
_secretKey = await _secureStorage.read(
key: secretKeyKey,
);
_authSecretKey = await _secureStorage.read(
key: authSecretKeyKey,
);
if (_key == null) {
await logout(autoLogout: true);
}
}
}
Future<void> logout({bool autoLogout = false}) async {
await _preferences.clear();
for (String key in onlineSecureKeys) {
await _secureStorage.delete(
key: key,
);
}
await AuthenticatorDB.instance.clearTable();
_key = null;
_cachedToken = null;
_secretKey = null;
_authSecretKey = null;
await super.logout();
Bus.instance.fire(SignedOutEvent());
}
Future<KeyGenResult> generateKey(String password) async {
// Create a master key
final masterKey = CryptoUtil.generateKey();
// Create a recovery key
final recoveryKey = CryptoUtil.generateKey();
// Encrypt master key and recovery key with each other
final encryptedMasterKey = CryptoUtil.encryptSync(masterKey, recoveryKey);
final encryptedRecoveryKey = CryptoUtil.encryptSync(recoveryKey, masterKey);
// Derive a key from the password that will be used to encrypt and
// decrypt the master key
final kekSalt = CryptoUtil.getSaltToDeriveKey();
final derivedKeyResult = await CryptoUtil.deriveSensitiveKey(
utf8.encode(password),
kekSalt,
);
final loginKey = await CryptoUtil.deriveLoginKey(derivedKeyResult.key);
// Encrypt the key with this derived key
final encryptedKeyData =
CryptoUtil.encryptSync(masterKey, derivedKeyResult.key);
// Generate a public-private keypair and encrypt the latter
final keyPair = CryptoUtil.generateKeyPair();
final encryptedSecretKeyData =
CryptoUtil.encryptSync(keyPair.secretKey.extractBytes(), masterKey);
final attributes = KeyAttributes(
CryptoUtil.bin2base64(kekSalt),
CryptoUtil.bin2base64(encryptedKeyData.encryptedData!),
CryptoUtil.bin2base64(encryptedKeyData.nonce!),
CryptoUtil.bin2base64(keyPair.publicKey),
CryptoUtil.bin2base64(encryptedSecretKeyData.encryptedData!),
CryptoUtil.bin2base64(encryptedSecretKeyData.nonce!),
derivedKeyResult.memLimit,
derivedKeyResult.opsLimit,
CryptoUtil.bin2base64(encryptedMasterKey.encryptedData!),
CryptoUtil.bin2base64(encryptedMasterKey.nonce!),
CryptoUtil.bin2base64(encryptedRecoveryKey.encryptedData!),
CryptoUtil.bin2base64(encryptedRecoveryKey.nonce!),
);
final privateAttributes = PrivateKeyAttributes(
CryptoUtil.bin2base64(masterKey),
CryptoUtil.bin2hex(recoveryKey),
CryptoUtil.bin2base64(keyPair.secretKey.extractBytes()),
);
return KeyGenResult(attributes, privateAttributes, loginKey);
}
Future<Tuple2<KeyAttributes, Uint8List>> getAttributesForNewPassword(
String password,
) async {
// Get master key
final masterKey = getKey();
// Derive a key from the password that will be used to encrypt and
// decrypt the master key
final kekSalt = CryptoUtil.getSaltToDeriveKey();
final derivedKeyResult = await CryptoUtil.deriveSensitiveKey(
utf8.encode(password),
kekSalt,
);
final loginKey = await CryptoUtil.deriveLoginKey(derivedKeyResult.key);
// Encrypt the key with this derived key
final encryptedKeyData =
CryptoUtil.encryptSync(masterKey!, derivedKeyResult.key);
final existingAttributes = getKeyAttributes();
final updatedAttributes = existingAttributes!.copyWith(
kekSalt: CryptoUtil.bin2base64(kekSalt),
encryptedKey: CryptoUtil.bin2base64(encryptedKeyData.encryptedData!),
keyDecryptionNonce: CryptoUtil.bin2base64(encryptedKeyData.nonce!),
memLimit: derivedKeyResult.memLimit,
opsLimit: derivedKeyResult.opsLimit,
);
return Tuple2(updatedAttributes, loginKey);
}
// decryptSecretsAndGetLoginKey decrypts the master key and recovery key
// with the given password and save them in local secure storage.
// This method also returns the keyEncKey that can be used for performing
// SRP setup for existing users.
Future<Uint8List> decryptSecretsAndGetKeyEncKey(
String password,
KeyAttributes attributes, {
Uint8List? keyEncryptionKey,
}) async {
_logger.info('Start decryptAndSaveSecrets');
keyEncryptionKey ??= await CryptoUtil.deriveKey(
utf8.encode(password),
CryptoUtil.base642bin(attributes.kekSalt),
attributes.memLimit,
attributes.opsLimit,
);
_logger.info('user-key done');
Uint8List key;
try {
key = CryptoUtil.decryptSync(
CryptoUtil.base642bin(attributes.encryptedKey),
keyEncryptionKey,
CryptoUtil.base642bin(attributes.keyDecryptionNonce),
);
} catch (e) {
_logger.severe('master-key failed, incorrect password?', e);
throw Exception("Incorrect password");
}
_logger.info("master-key done");
await setKey(CryptoUtil.bin2base64(key));
final secretKey = CryptoUtil.decryptSync(
CryptoUtil.base642bin(attributes.encryptedSecretKey),
key,
CryptoUtil.base642bin(attributes.secretKeyDecryptionNonce),
);
_logger.info("secret-key done");
await setSecretKey(CryptoUtil.bin2base64(secretKey));
final token = CryptoUtil.openSealSync(
CryptoUtil.base642bin(getEncryptedToken()!),
CryptoUtil.base642bin(attributes.publicKey),
secretKey,
);
_logger.info('appToken done');
await setToken(
CryptoUtil.bin2base64(token, urlSafe: true),
);
return keyEncryptionKey;
}
Future<void> recover(String recoveryKey) async {
// check if user has entered mnemonic code
if (recoveryKey.contains(' ')) {
final split = recoveryKey.split(' ');
if (split.length != mnemonicKeyWordCount) {
String wordThatIsFollowedByEmptySpaceInSplit = '';
for (int i = 0; i < split.length; i++) {
String word = split[i];
if (word.isEmpty) {
wordThatIsFollowedByEmptySpaceInSplit =
'\n\nExtra space after word at position $i';
break;
}
}
throw AssertionError(
'\nRecovery code should have $mnemonicKeyWordCount words, '
'found ${split.length} words instead.$wordThatIsFollowedByEmptySpaceInSplit',
);
}
recoveryKey = bip39.mnemonicToEntropy(recoveryKey);
}
final attributes = getKeyAttributes();
Uint8List masterKey;
try {
masterKey = await CryptoUtil.decrypt(
CryptoUtil.base642bin(attributes!.masterKeyEncryptedWithRecoveryKey),
CryptoUtil.hex2bin(recoveryKey),
CryptoUtil.base642bin(attributes.masterKeyDecryptionNonce),
);
} catch (e) {
_logger.severe(e);
rethrow;
}
await setKey(CryptoUtil.bin2base64(masterKey));
final secretKey = CryptoUtil.decryptSync(
CryptoUtil.base642bin(attributes.encryptedSecretKey),
masterKey,
CryptoUtil.base642bin(attributes.secretKeyDecryptionNonce),
);
await setSecretKey(CryptoUtil.bin2base64(secretKey));
final token = CryptoUtil.openSealSync(
CryptoUtil.base642bin(getEncryptedToken()!),
CryptoUtil.base642bin(attributes.publicKey),
secretKey,
);
await setToken(
CryptoUtil.bin2base64(token, urlSafe: true),
);
}
String getHttpEndpoint() {
return _preferences.getString(endPointKey) ?? endpoint;
}
Future<void> setHttpEndpoint(String endpoint) async {
await _preferences.setString(endPointKey, endpoint);
Bus.instance.fire(EndpointUpdatedEvent());
}
String? getToken() {
_cachedToken ??= _preferences.getString(tokenKey);
return _cachedToken;
}
bool isLoggedIn() {
return getToken() != null;
}
Future<void> setToken(String token) async {
_cachedToken = token;
await _preferences.setString(tokenKey, token);
Bus.instance.fire(SignedInEvent());
}
Future<void> setEncryptedToken(String encryptedToken) async {
await _preferences.setString(encryptedTokenKey, encryptedToken);
}
String? getEncryptedToken() {
return _preferences.getString(encryptedTokenKey);
}
String? getEmail() {
return _preferences.getString(emailKey);
}
Future<void> setEmail(String email) async {
await _preferences.setString(emailKey, email);
}
int? getUserID() {
return _preferences.getInt(userIDKey);
}
Future<void> setUserID(int userID) async {
await _preferences.setInt(userIDKey, userID);
}
Future<void> setKeyAttributes(KeyAttributes attributes) async {
await _preferences.setString(keyAttributesKey, attributes.toJson());
}
KeyAttributes? getKeyAttributes() {
final jsonValue = _preferences.getString(keyAttributesKey);
if (jsonValue == null) {
return null;
} else {
return KeyAttributes.fromJson(jsonValue);
}
}
Future<void> setKey(String key) async {
_key = key;
await _secureStorage.write(
key: keyKey,
value: key,
);
}
Future<void> setSecretKey(String? secretKey) async {
_secretKey = secretKey;
await _secureStorage.write(
key: secretKeyKey,
value: secretKey,
);
}
Future<void> setAuthSecretKey(String? authSecretKey) async {
@@ -54,6 +406,14 @@ class Configuration extends BaseConfiguration {
);
}
Uint8List? getKey() {
return _key == null ? null : CryptoUtil.base642bin(_key!);
}
Uint8List? getSecretKey() {
return _secretKey == null ? null : CryptoUtil.base642bin(_secretKey!);
}
Uint8List? getAuthSecretKey() {
return _authSecretKey == null
? null
@@ -66,6 +426,24 @@ class Configuration extends BaseConfiguration {
: CryptoUtil.base642bin(_offlineAuthKey!);
}
Uint8List getRecoveryKey() {
final keyAttributes = getKeyAttributes()!;
return CryptoUtil.decryptSync(
CryptoUtil.base642bin(keyAttributes.recoveryKeyEncryptedWithMasterKey),
getKey()!,
CryptoUtil.base642bin(keyAttributes.recoveryKeyDecryptionNonce),
);
}
// Caution: This directory is cleared on app start
String getTempDirectory() {
return _tempDirectory;
}
bool hasConfiguredAccount() {
return getToken() != null && _key != null;
}
bool hasOptedForOfflineMode() {
return _preferences.getBool(hasOptedForOfflineModeKey) ?? false;
}
@@ -86,4 +464,16 @@ class Configuration extends BaseConfiguration {
}
await _preferences.setBool(hasOptedForOfflineModeKey, true);
}
void setVolatilePassword(String volatilePassword) {
_volatilePassword = volatilePassword;
}
void resetVolatilePassword() {
_volatilePassword = null;
}
String? getVolatilePassword() {
return _volatilePassword;
}
}

View File

@@ -3,12 +3,13 @@ import 'dart:collection';
import 'dart:core';
import 'dart:io';
import 'package:ente_logging/tunneled_transport.dart';
import 'package:ente_auth/core/logging/tunneled_transport.dart';
import 'package:ente_auth/models/typedefs.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
import 'package:logging/logging.dart' as log;
import 'package:logging/logging.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
@@ -16,9 +17,6 @@ import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:uuid/uuid.dart';
/// Type definition for functions that may return a value or Future
typedef FutureOrVoidCallback = dynamic Function();
extension SuperString on String {
Iterable<String> chunked(int chunkSize) sync* {
var start = 0;
@@ -36,7 +34,7 @@ extension SuperString on String {
}
}
extension SuperLogRecord on log.LogRecord {
extension SuperLogRecord on LogRecord {
String toPrettyString([String? extraLines]) {
final header = "[$loggerName] [$level] [$time]";
@@ -138,7 +136,7 @@ class LogConfig {
class SuperLogging {
/// The logger for SuperLogging
static final $ = log.Logger('ente_logging');
static final $ = Logger('ente_logging');
/// The current super logging configuration
static late LogConfig config;
@@ -170,8 +168,8 @@ class SuperLogging {
setupSentry().ignore();
}
log.Logger.root.level = log.Level.ALL;
log.Logger.root.onRecord.listen(onLogRecord);
Logger.root.level = Level.ALL;
Logger.root.onRecord.listen(onLogRecord);
if (!enable) {
$.info("detected debug mode; sentry & file logging disabled.");
@@ -226,7 +224,7 @@ class SuperLogging {
static String _lastExtraLines = '';
static Future onLogRecord(log.LogRecord rec) async {
static Future onLogRecord(LogRecord rec) async {
// log misc info if it changed
String? extraLines = "app version: '$appVersion'\n";
if (extraLines != _lastExtraLines) {

View File

@@ -1,13 +1,14 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:ente_configuration/base_configuration.dart';
import 'package:ente_events/event_bus.dart';
import 'package:ente_events/models/endpoint_updated_event.dart';
import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/core/event_bus.dart';
import 'package:ente_auth/events/endpoint_updated_event.dart';
import 'package:ente_auth/utils/package_info_util.dart';
import 'package:ente_auth/utils/platform_util.dart';
import 'package:fk_user_agent/fk_user_agent.dart';
import 'package:flutter/foundation.dart';
import 'package:native_dio_adapter/native_dio_adapter.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:ua_client_hints/ua_client_hints.dart';
import 'package:uuid/uuid.dart';
int kConnectTimeout = 15000;
@@ -16,23 +17,20 @@ class Network {
late Dio _dio;
late Dio _enteDio;
Future<void> init(BaseConfiguration configuration) async {
final bool isMobile = Platform.isAndroid || Platform.isIOS;
String? ua;
if (isMobile) {
ua = await userAgent();
}
final packageInfo = await PackageInfo.fromPlatform();
final version = packageInfo.version;
final packageName = packageInfo.packageName;
final endpoint = configuration.getHttpEndpoint();
Future<void> init() async {
if (PlatformUtil.isMobile()) await FkUserAgent.init();
final packageInfo = await PackageInfoUtil().getPackageInfo();
final version = PackageInfoUtil().getVersion(packageInfo);
final packageName = PackageInfoUtil().getPackageName(packageInfo);
final endpoint = Configuration.instance.getHttpEndpoint();
_dio = Dio(
BaseOptions(
connectTimeout: Duration(milliseconds: kConnectTimeout),
headers: {
HttpHeaders.userAgentHeader:
isMobile ? ua! : Platform.operatingSystem,
HttpHeaders.userAgentHeader: PlatformUtil.isMobile()
? FkUserAgent.userAgent
: Platform.operatingSystem,
'X-Client-Version': version,
'X-Client-Package': packageName,
},
@@ -44,8 +42,8 @@ class Network {
baseUrl: endpoint,
connectTimeout: Duration(milliseconds: kConnectTimeout),
headers: {
if (isMobile)
HttpHeaders.userAgentHeader: ua!
if (PlatformUtil.isMobile())
HttpHeaders.userAgentHeader: FkUserAgent.userAgent
else
HttpHeaders.userAgentHeader: Platform.operatingSystem,
'X-Client-Version': version,
@@ -57,12 +55,12 @@ class Network {
_dio.httpClientAdapter = NativeAdapter();
_enteDio.httpClientAdapter = NativeAdapter();
_setupInterceptors(configuration);
_setupInterceptors(endpoint);
Bus.instance.on<EndpointUpdatedEvent>().listen((event) {
final endpoint = configuration.getHttpEndpoint();
final endpoint = Configuration.instance.getHttpEndpoint();
_enteDio.options.baseUrl = endpoint;
_setupInterceptors(configuration);
_setupInterceptors(endpoint);
});
}
@@ -73,12 +71,12 @@ class Network {
Dio getDio() => _dio;
Dio get enteDio => _enteDio;
void _setupInterceptors(BaseConfiguration configuration) {
void _setupInterceptors(String endpoint) {
_dio.interceptors.clear();
_dio.interceptors.add(RequestIdInterceptor());
_enteDio.interceptors.clear();
_enteDio.interceptors.add(EnteRequestInterceptor(configuration));
_enteDio.interceptors.add(EnteRequestInterceptor(endpoint));
}
}
@@ -92,21 +90,21 @@ class RequestIdInterceptor extends Interceptor {
}
class EnteRequestInterceptor extends Interceptor {
final BaseConfiguration configuration;
final String endpoint;
EnteRequestInterceptor(this.configuration);
EnteRequestInterceptor(this.endpoint);
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
if (kDebugMode) {
assert(
options.baseUrl == configuration.getHttpEndpoint(),
options.baseUrl == endpoint,
"interceptor should only be used for API endpoint",
);
}
options.headers
.putIfAbsent("x-request-id", () => const Uuid().v4().toString());
final String? tokenValue = configuration.getToken();
final String? tokenValue = Configuration.instance.getToken();
if (tokenValue != null) {
options.headers.putIfAbsent("X-Auth-Token", () => tokenValue);
}

View File

@@ -39,7 +39,7 @@ final lightThemeData = ThemeData(
bodyLarge: const TextStyle(color: Colors.orange),
),
cardColor: const Color.fromRGBO(250, 250, 250, 1.0),
dialogTheme: const DialogThemeData().copyWith(
dialogTheme: const DialogTheme().copyWith(
backgroundColor: const Color.fromRGBO(250, 250, 250, 1.0), //
titleTextStyle: const TextStyle(
color: Colors.black,
@@ -150,7 +150,7 @@ final darkThemeData = ThemeData(
elevation: 0,
),
cardColor: const Color.fromRGBO(10, 15, 15, 1.0),
dialogTheme: const DialogThemeData().copyWith(
dialogTheme: const DialogTheme().copyWith(
backgroundColor: const Color.fromRGBO(15, 15, 15, 1.0),
titleTextStyle: const TextStyle(
color: Colors.white,
@@ -275,7 +275,7 @@ TextTheme _buildTextTheme(Color textColor) {
fontWeight: FontWeight.w500,
),
bodySmall: TextStyle(
color: textColor.withValues(alpha: 0.4),
color: textColor.withOpacity(0.4),
fontSize: 10,
fontWeight: FontWeight.w500,
),
@@ -343,7 +343,7 @@ extension CustomColorScheme on ColorScheme {
: const Color.fromRGBO(48, 48, 48, 0.5);
Color get iconColor => brightness == Brightness.light
? const Color.fromRGBO(0, 0, 0, 1).withValues(alpha: 0.75)
? const Color.fromRGBO(0, 0, 0, 1).withOpacity(0.75)
: const Color.fromRGBO(255, 255, 255, 1);
Color get bgColorForQuestions => brightness == Brightness.light
@@ -354,7 +354,7 @@ extension CustomColorScheme on ColorScheme {
Color get cupertinoPickerTopColor => brightness == Brightness.light
? const Color.fromARGB(255, 238, 238, 238)
: const Color.fromRGBO(255, 255, 255, 1).withValues(alpha: 0.1);
: const Color.fromRGBO(255, 255, 255, 1).withOpacity(0.1);
Color get stepProgressUnselectedColor => brightness == Brightness.light
? const Color.fromRGBO(196, 196, 196, 0.6)
@@ -381,20 +381,20 @@ extension CustomColorScheme on ColorScheme {
: const Color.fromRGBO(20, 20, 20, 1);
Color get galleryThumbDrawColor => brightness == Brightness.light
? const Color.fromRGBO(0, 0, 0, 1).withValues(alpha: 0.8)
: const Color.fromRGBO(255, 255, 255, 1).withValues(alpha: 0.5);
? const Color.fromRGBO(0, 0, 0, 1).withOpacity(0.8)
: const Color.fromRGBO(255, 255, 255, 1).withOpacity(0.5);
Color get backupEnabledBgColor => brightness == Brightness.light
? const Color.fromRGBO(230, 230, 230, 0.95)
: const Color.fromRGBO(10, 40, 40, 0.3);
Color get dotsIndicatorActiveColor => brightness == Brightness.light
? const Color.fromRGBO(0, 0, 0, 1).withValues(alpha: 0.5)
: const Color.fromRGBO(255, 255, 255, 1).withValues(alpha: 0.5);
? const Color.fromRGBO(0, 0, 0, 1).withOpacity(0.5)
: const Color.fromRGBO(255, 255, 255, 1).withOpacity(0.5);
Color get dotsIndicatorInactiveColor => brightness == Brightness.light
? const Color.fromRGBO(0, 0, 0, 1).withValues(alpha: 0.12)
: const Color.fromRGBO(255, 255, 255, 1).withValues(alpha: 0.12);
? const Color.fromRGBO(0, 0, 0, 1).withOpacity(0.12)
: const Color.fromRGBO(255, 255, 255, 1).withOpacity(0.12);
Color get toastTextColor => brightness == Brightness.light
? const Color.fromRGBO(255, 255, 255, 1)
@@ -409,8 +409,8 @@ extension CustomColorScheme on ColorScheme {
: const Color.fromRGBO(100, 100, 100, 1);
Color get themeSwitchInactiveIconColor => brightness == Brightness.light
? const Color.fromRGBO(0, 0, 0, 1).withValues(alpha: 0.5)
: const Color.fromRGBO(255, 255, 255, 1).withValues(alpha: 0.5);
? const Color.fromRGBO(0, 0, 0, 1).withOpacity(0.5)
: const Color.fromRGBO(255, 255, 255, 1).withOpacity(0.5);
Color get searchResultsColor => brightness == Brightness.light
? const Color.fromRGBO(245, 245, 245, 1.0)
@@ -421,8 +421,8 @@ extension CustomColorScheme on ColorScheme {
: const Color.fromRGBO(150, 150, 150, 1);
Color get searchResultsBackgroundColor => brightness == Brightness.light
? Colors.black.withValues(alpha: 0.32)
: Colors.black.withValues(alpha: 0.64);
? Colors.black.withOpacity(0.32)
: Colors.black.withOpacity(0.64);
Color get codeCardBackgroundColor => brightness == Brightness.light
? const Color.fromRGBO(246, 246, 246, 1)

View File

@@ -1,3 +1,3 @@
import 'package:ente_events/models/event.dart';
import 'package:ente_auth/events/event.dart';
class CodesUpdatedEvent extends Event {}

View File

@@ -0,0 +1,3 @@
import 'package:ente_auth/events/event.dart';
class EndpointUpdatedEvent extends Event {}

View File

@@ -1,3 +1,3 @@
import 'package:ente_events/models/event.dart';
import 'package:ente_auth/events/event.dart';
class IconsChangedEvent extends Event {}

View File

@@ -0,0 +1,5 @@
import 'package:ente_auth/events/event.dart';
// NotificationEvent event is used to re-fresh the UI to show latest notification
// (if any)
class NotificationEvent extends Event {}

View File

@@ -0,0 +1,3 @@
import 'package:ente_auth/events/event.dart';
class SignedInEvent extends Event {}

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