Compare commits
75 Commits
face_thumb
...
usearch_up
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a694bf9b6c | ||
|
|
bfcfa691a2 | ||
|
|
2703c6a33a | ||
|
|
3ad94f362a | ||
|
|
8508ca74f2 | ||
|
|
eed12c2089 | ||
|
|
889aed6024 | ||
|
|
ac7840cbfd | ||
|
|
1f1304ca5b | ||
|
|
94098d8a07 | ||
|
|
4b9c5fcb73 | ||
|
|
6ed16e5e02 | ||
|
|
82a8e504af | ||
|
|
cc1660d9af | ||
|
|
52b6fc108b | ||
|
|
8b3b20aa93 | ||
|
|
408b0bfe2d | ||
|
|
655be76428 | ||
|
|
9fedf8d6b7 | ||
|
|
7c4e775872 | ||
|
|
ecfa640c28 | ||
|
|
1997eb20f3 | ||
|
|
726425bbb6 | ||
|
|
c068f26604 | ||
|
|
e60c2b1192 | ||
|
|
beb049f817 | ||
|
|
7021c9fe02 | ||
|
|
c2d5dece9e | ||
|
|
b76d41b84d | ||
|
|
3b9c76649d | ||
|
|
62ed8b6975 | ||
|
|
2422dba4d4 | ||
|
|
eb1916e3a3 | ||
|
|
df0d9137a6 | ||
|
|
fc36b87965 | ||
|
|
63d90ea275 | ||
|
|
bb7f8a5eef | ||
|
|
2f5a02ec43 | ||
|
|
d411d91966 | ||
|
|
54b712953a | ||
|
|
27ad020adc | ||
|
|
ce112bd4d7 | ||
|
|
2ffb73d053 | ||
|
|
6478d438b5 | ||
|
|
d87069eb4c | ||
|
|
5447350ab1 | ||
|
|
ea1a2960bf | ||
|
|
832f2c451e | ||
|
|
715c7c23a7 | ||
|
|
e9c2e40a43 | ||
|
|
603c275c09 | ||
|
|
7b9d6df2fd | ||
|
|
a4afecef3d | ||
|
|
4d9bfb89ae | ||
|
|
f2a74bd35e | ||
|
|
8c65a21b86 | ||
|
|
a07e8477fb | ||
|
|
8b489e9ced | ||
|
|
77e2bb1d46 | ||
|
|
4ce24e080a | ||
|
|
4e5ca3dca6 | ||
|
|
2ed155ab47 | ||
|
|
65e71e3caf | ||
|
|
ee5efbcfcc | ||
|
|
6cf4530f7d | ||
|
|
e6ee09ca30 | ||
|
|
6d2f53b86c | ||
|
|
6500748c5a | ||
|
|
120dbeb4fc | ||
|
|
c42807487b | ||
|
|
e707e24da9 | ||
|
|
af817ec439 | ||
|
|
ddb44d8fd7 | ||
|
|
778822b12d | ||
|
|
9599ec3236 |
2
.github/workflows/auth-internal-release.yml
vendored
2
.github/workflows/auth-internal-release.yml
vendored
@@ -4,7 +4,7 @@ on:
|
||||
workflow_dispatch: # Allow manually running the action
|
||||
|
||||
env:
|
||||
FLUTTER_VERSION: "3.29.3"
|
||||
FLUTTER_VERSION: "3.24.3"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
2
.github/workflows/auth-lint.yml
vendored
2
.github/workflows/auth-lint.yml
vendored
@@ -8,7 +8,7 @@ on:
|
||||
- ".github/workflows/auth-lint.yml"
|
||||
|
||||
env:
|
||||
FLUTTER_VERSION: "3.29.3"
|
||||
FLUTTER_VERSION: "3.24.3"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
4
.github/workflows/auth-release.yml
vendored
4
.github/workflows/auth-release.yml
vendored
@@ -29,7 +29,7 @@ on:
|
||||
- "auth-v*"
|
||||
|
||||
env:
|
||||
FLUTTER_VERSION: "3.29.3"
|
||||
FLUTTER_VERSION: "3.24.3"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -98,7 +98,7 @@ jobs:
|
||||
|
||||
- name: Install appimagetool
|
||||
run: |
|
||||
wget -O appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
|
||||
wget -O appimagetool "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage"
|
||||
chmod +x appimagetool
|
||||
mv appimagetool /usr/local/bin/
|
||||
|
||||
|
||||
2
.github/workflows/auth-win-sign.yml
vendored
2
.github/workflows/auth-win-sign.yml
vendored
@@ -5,7 +5,7 @@ on:
|
||||
workflow_dispatch: # Allow manually running the action
|
||||
|
||||
env:
|
||||
FLUTTER_VERSION: "3.29.3"
|
||||
FLUTTER_VERSION: "3.24.3"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
@@ -4,7 +4,7 @@ on:
|
||||
workflow_dispatch: # Allow manually running the action
|
||||
|
||||
env:
|
||||
FLUTTER_VERSION: "3.29.3"
|
||||
FLUTTER_VERSION: "3.24.3"
|
||||
RUST_VERSION: "1.85.1"
|
||||
|
||||
permissions:
|
||||
|
||||
@@ -4,7 +4,7 @@ on:
|
||||
workflow_dispatch: # Allow manually running the action
|
||||
|
||||
env:
|
||||
FLUTTER_VERSION: "3.29.3"
|
||||
FLUTTER_VERSION: "3.24.3"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
2
.github/workflows/mobile-lint.yml
vendored
2
.github/workflows/mobile-lint.yml
vendored
@@ -8,7 +8,7 @@ on:
|
||||
- ".github/workflows/mobile-lint.yml"
|
||||
|
||||
env:
|
||||
FLUTTER_VERSION: "3.29.3"
|
||||
FLUTTER_VERSION: "3.24.3"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
2
.github/workflows/mobile-release.yml
vendored
2
.github/workflows/mobile-release.yml
vendored
@@ -9,7 +9,7 @@ on:
|
||||
- "photos-v*"
|
||||
|
||||
env:
|
||||
FLUTTER_VERSION: "3.29.3"
|
||||
FLUTTER_VERSION: "3.24.3"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
1
auth/assets/simple-icons
Submodule
1
auth/assets/simple-icons
Submodule
Submodule auth/assets/simple-icons added at 6dcfdc2f58
1
auth/flutter
Submodule
1
auth/flutter
Submodule
Submodule auth/flutter added at 5874a72aa4
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"flutter": "3.29.3"
|
||||
"flutter": "3.24.3"
|
||||
}
|
||||
3
mobile/apps/auth/.gitignore
vendored
3
mobile/apps/auth/.gitignore
vendored
@@ -44,5 +44,4 @@ android/key.properties
|
||||
dist/
|
||||
|
||||
# FVM Version Cache
|
||||
.fvm/
|
||||
lib/l10n/arb/*.dart
|
||||
.fvm/
|
||||
@@ -44,7 +44,7 @@ or managing your secrets, please use our mobile or desktop app.
|
||||
|
||||
## 🧑💻 Build from source
|
||||
|
||||
1. [Install Flutter v3.29.3](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`
|
||||
|
||||
|
||||
@@ -739,10 +739,6 @@
|
||||
"lu.ma"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "MangaDex",
|
||||
"slug": "mangadex"
|
||||
},
|
||||
{
|
||||
"title": "Marketplace.tf",
|
||||
"slug": "marketplacedottf"
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 5.0 KiB |
@@ -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 --")
|
||||
@@ -1,5 +0,0 @@
|
||||
#
|
||||
# Generated file, do not edit.
|
||||
#
|
||||
|
||||
command script import --relative-to-command-file flutter_lldb_helper.py
|
||||
@@ -232,44 +232,44 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
app_links: e7a6750a915a9e161c58d91bc610e8cd1d4d0ad0
|
||||
connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db
|
||||
cupertino_http: 947a233f40cfea55167a49f2facc18434ea117ba
|
||||
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
|
||||
app_links: 3da4c36b46cac3bf24eb897f1a6ce80bda109874
|
||||
connectivity_plus: 3f6c9057f4cd64198dc826edfb0542892f825343
|
||||
cupertino_http: 94ac07f5ff090b8effa6c5e2c47871d48ab7c86c
|
||||
device_info_plus: 335f3ce08d2e174b9fdc3db3db0f4e3b1f66bd89
|
||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||
file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655
|
||||
file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808
|
||||
fk_user_agent: 1f47ec39291e8372b1d692b50084b0d54103c545
|
||||
file_picker: 9b3292d7c8bc68c8a7bf8eb78f730e49c8efc517
|
||||
file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6
|
||||
fk_user_agent: 137145b086229251761678fe034da53753f4ce59
|
||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||
flutter_email_sender: 10a22605f92809a11ef52b2f412db806c6082d40
|
||||
flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4
|
||||
flutter_local_authentication: 1172a4dd88f6306dadce067454e2c4caf07977bb
|
||||
flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086
|
||||
flutter_native_splash: edf599c81f74d093a4daf8e17bd7a018854bc778
|
||||
flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12
|
||||
fluttertoast: e9a18c7be5413da53898f660530c56f35edfba9c
|
||||
local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3
|
||||
move_to_background: 39a5b79b26d577b0372cbe8a8c55e7aa9fcd3a2d
|
||||
flutter_email_sender: 2397f5e84aaacfb61af569637a963e7c687858d8
|
||||
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
||||
flutter_local_authentication: 989278c681612f1ee0e36019e149137f114b9d7f
|
||||
flutter_local_notifications: ad39620c743ea4c15127860f4b5641649a988100
|
||||
flutter_native_splash: 35ddbc7228eafcb3969dcc5f1fbbe27c1145a4f0
|
||||
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
||||
fluttertoast: 76fea30fcf04176325f6864c87306927bd7d2038
|
||||
local_auth_darwin: 553ce4f9b16d3fdfeafce9cf042e7c9f77c1c391
|
||||
move_to_background: 155f7bfbd34d43ad847cb630d2d2d87c17199710
|
||||
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
|
||||
objective_c: 77e887b5ba1827970907e10e832eec1683f3431d
|
||||
objective_c: 89e720c30d716b036faf9c9684022048eee1eee2
|
||||
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
|
||||
package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c
|
||||
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
|
||||
privacy_screen: 1a131c052ceb3c3659934b003b0d397c2381a24e
|
||||
qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e
|
||||
package_info_plus: 580e9a5f1b6ca5594e7c9ed5f92d1dfb2a66b5e1
|
||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||
privacy_screen: 3159a541f5d3a31bea916cfd4e58f9dc722b3fd4
|
||||
qr_code_scanner: d77f94ecc9abf96d9b9b8fc04ef13f611e5a147a
|
||||
SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868
|
||||
Sentry: da60d980b197a46db0b35ea12cb8f39af48d8854
|
||||
sentry_flutter: 2df8b0aab7e4aba81261c230cbea31c82a62dd1b
|
||||
share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad
|
||||
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
|
||||
sodium_libs: 1faae17af662384acbd13e41867a0008cd2e2318
|
||||
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
|
||||
sentry_flutter: 27892878729f42701297c628eb90e7c6529f3684
|
||||
share_plus: 011d6fb4f9d2576b83179a3a5c5e323202cdabcf
|
||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
||||
sodium_libs: 6c6d0e83f4ee427c6464caa1f1bdc2abf3ca0b7f
|
||||
sqflite: c35dad70033b8862124f8337cc994a809fcd9fa3
|
||||
sqlite3: 0bb0e6389d824e40296f531b858a2a0b71c0d2fb
|
||||
sqlite3_flutter_libs: c00457ebd31e59fa6bb830380ddba24d44fbcd3b
|
||||
sqlite3_flutter_libs: 9379996d65aa23dcda7585a5b58766cebe0aa042
|
||||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||
Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e
|
||||
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
|
||||
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
||||
|
||||
PODFILE CHECKSUM: 78f002751f1a8f65042b8da97902ba4124271c5a
|
||||
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -40,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;
|
||||
});
|
||||
@@ -82,7 +82,7 @@ class _AppState extends State<App>
|
||||
UpdateService.instance.getLatestVersionInfo(),
|
||||
);
|
||||
},
|
||||
barrierColor: Colors.black.withValues(alpha: 0.85),
|
||||
barrierColor: Colors.black.withOpacity(0.85),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -78,7 +78,6 @@
|
||||
"contactSupport": "Звярнуцца ў службу падтрымкі",
|
||||
"rateUsOnStore": "Ацаніць нас у {storeName}",
|
||||
"blog": "Блог",
|
||||
"merchandise": "Тавары",
|
||||
"verifyPassword": "Праверыць пароль",
|
||||
"pleaseWait": "Пачакайце...",
|
||||
"generatingEncryptionKeysTitle": "Генерацыя ключоў шыфравання...",
|
||||
@@ -86,9 +85,6 @@
|
||||
"useRecoveryKey": "Выкарыстоўваць ключ аднаўлення",
|
||||
"incorrectPasswordTitle": "Няправільны пароль",
|
||||
"welcomeBack": "З вяртаннем!",
|
||||
"emailAlreadyRegistered": "Электронная пошта ўжо зарэгістравана.",
|
||||
"emailNotRegistered": "Электронная пошта не зарэгістравана.",
|
||||
"madeWithLoveAtPrefix": "зроблена з ❤️ у ",
|
||||
"changeEmail": "Змяніць адрас электроннай пошты",
|
||||
"changePassword": "Змяніць пароль",
|
||||
"data": "Даныя",
|
||||
@@ -98,13 +94,9 @@
|
||||
"passwordForDecryptingExport": "Пароль для дэшыфроўкі экспартавання",
|
||||
"passwordEmptyError": "Пароль не можа быць пустым",
|
||||
"importFromApp": "Імпартаваць коды з {appName}",
|
||||
"importSelectJsonFile": "Выбраць файл JSON",
|
||||
"importSelectAppExport": "Выберыце файл экспартавання {appName}",
|
||||
"exportCodes": "Экспартаваць коды",
|
||||
"importLabel": "Імпарт",
|
||||
"selectFile": "Выбраць файл",
|
||||
"emailVerificationToggle": "Праверка эл. пошты",
|
||||
"authenticateGeneric": "Прайдзіце аўтэнтыфікацыю",
|
||||
"ok": "OK",
|
||||
"cancel": "Скасаваць",
|
||||
"yes": "Так",
|
||||
@@ -121,29 +113,19 @@
|
||||
"enterYourPasswordHint": "Увядзіце ваш пароль",
|
||||
"forgotPassword": "Забылі пароль",
|
||||
"oops": "Вой",
|
||||
"suggestFeatures": "Прапанаваць функцыю",
|
||||
"faq": "Частыя пытанні",
|
||||
"leaveFamily": "Пакінуць сямейны план",
|
||||
"inFamilyPlanMessage": "Вы ўдзельнік сямейнага плана!",
|
||||
"scan": "Сканіраваць",
|
||||
"scanACode": "Сканіраваць код",
|
||||
"verify": "Праверыць",
|
||||
"verifyEmail": "Праверыць электронную пошту",
|
||||
"lostDeviceTitle": "Згубілі прыладу?",
|
||||
"twoFactorAuthTitle": "Двухфактарная аўтэнтыфікацыя",
|
||||
"passkeyAuthTitle": "Праверка ключа доступу",
|
||||
"verifyPasskey": "Праверыць ключ доступу",
|
||||
"loginWithTOTP": "Увайсці з TOTP",
|
||||
"recoverAccount": "Аднавіць уліковы запіс",
|
||||
"enterRecoveryKeyHint": "Увядзіце свой ключ аднаўлення",
|
||||
"recover": "Аднавіць",
|
||||
"invalidQRCode": "Памылковы QR-код",
|
||||
"noRecoveryKeyTitle": "Няма ключа аднаўлення?",
|
||||
"enterEmailHint": "Увядзіце свой адрас электроннай пошты",
|
||||
"enterNewEmailHint": "Увядзіце свой новы адрас электроннай пошты",
|
||||
"invalidEmailTitle": "Памылковы адрас электроннай пошты",
|
||||
"deleteAccount": "Выдаліць уліковы запіс",
|
||||
"yesSendFeedbackAction": "Так. Адправіць водгук",
|
||||
"noDeleteAccountAction": "Не, выдаліць уліковы запіс",
|
||||
"sendEmail": "Адправіць ліст",
|
||||
"createNewAccount": "Стварыць новы ўліковы запіс",
|
||||
@@ -158,21 +140,16 @@
|
||||
"social": "Сацыяльныя сеткі",
|
||||
"security": "Бяспека",
|
||||
"lockscreen": "Экран блакіроўкі",
|
||||
"viewActiveSessions": "Паглядзець актыўныя сеансы",
|
||||
"searchHint": "Пошук...",
|
||||
"search": "Пошук",
|
||||
"noResult": "Няма вынікаў",
|
||||
"addCode": "Дадаць код",
|
||||
"scanAQrCode": "Сканіраваць QR-код",
|
||||
"enterDetailsManually": "Увесці падрабязнасці ўручную",
|
||||
"edit": "Рэдагаваць",
|
||||
"share": "Абагуліць",
|
||||
"shareCodes": "Абагуліць коды",
|
||||
"restore": "Аднавіць",
|
||||
"copiedToClipboard": "Скапіявана ў буфер абмену",
|
||||
"copiedNextToClipboard": "Скапіяваць наступны код у буфер абмену",
|
||||
"error": "Памылка",
|
||||
"recoveryKeyCopiedToClipboard": "Ключ аднаўлення скапіяваны ў буфер абмену",
|
||||
"doThisLater": "Зрабіць гэта пазней",
|
||||
"saveKey": "Захаваць ключ",
|
||||
"save": "Захаваць",
|
||||
@@ -187,27 +164,19 @@
|
||||
"changePasswordTitle": "Змяніць пароль",
|
||||
"resetPasswordTitle": "Скінуць пароль",
|
||||
"encryptionKeys": "Ключы шыфравання",
|
||||
"passwordChangedSuccessfully": "Пароль паспяхова зменены",
|
||||
"generatingEncryptionKeys": "Генерацыя ключоў шыфравання...",
|
||||
"continueLabel": "Працягнуць",
|
||||
"insecureDevice": "Небяспечная прылада",
|
||||
"howItWorks": "Як гэта працуе",
|
||||
"logInLabel": "Увайсці",
|
||||
"logout": "Выйсці",
|
||||
"areYouSureYouWantToLogout": "Вы сапраўды хочаце выйсці?",
|
||||
"yesLogout": "Так, выйсці",
|
||||
"exit": "Выхад",
|
||||
"theme": "Тема",
|
||||
"lightTheme": "Светлая",
|
||||
"darkTheme": "Цёмная",
|
||||
"systemTheme": "Сістэманая",
|
||||
"verifyingRecoveryKey": "Праверка ключа аднаўлення...",
|
||||
"recoveryKeyVerified": "Ключ аднаўлення правераны",
|
||||
"recreatePasswordTitle": "Стварыць пароль паўторна",
|
||||
"invalidKey": "Памылковы ключ",
|
||||
"tryAgain": "Паспрабуйце яшчэ раз",
|
||||
"viewRecoveryKey": "Прагледзець ключ аднаўлення",
|
||||
"confirmRecoveryKey": "Пацвердзіце ключ аднаўлення",
|
||||
"confirmYourRecoveryKey": "Пацвердзіце свой ключ аднаўлення",
|
||||
"confirm": "Пацвердзіць",
|
||||
"emailYourLogs": "Адправіць журналы",
|
||||
@@ -252,22 +221,15 @@
|
||||
"pendingSyncs": "Папярэджанне",
|
||||
"pendingSyncsWarningBody": "Некаторыя вашы коды не былі зарэзерваваны.\n\nПераканайцеся, што ў вас ёсць іх рэзервовая копія перад выхадам з сістэмы.",
|
||||
"checkInboxAndSpamFolder": "Праверце свае ўваходныя лісты (і спам) для завяршэння праверкі",
|
||||
"tapToEnterCode": "Націсніце, каб увесці код",
|
||||
"resendEmail": "Адправіць ліст яшчэ раз",
|
||||
"manualSort": "Карыстальніцкая",
|
||||
"editOrder": "Рэдагаваць заказ",
|
||||
"mostFrequentlyUsed": "Часта выкарыстоўваюцца",
|
||||
"mostRecentlyUsed": "Нядаўна выкарыстаныя",
|
||||
"activeSessions": "Актыўныя сеансы",
|
||||
"terminateSession": "Перарваць сеанс?",
|
||||
"terminate": "Перарваць",
|
||||
"thisDevice": "Гэта прылада",
|
||||
"thisEmailIsAlreadyInUse": "Гэта электронная пошта ўжо выкарыстоўваецца",
|
||||
"yourVerificationCodeHasExpired": "Ваш праверачны код пратэрмінаваны",
|
||||
"incorrectCode": "Няправільны код",
|
||||
"emailChangedTo": "Электронная пошта зменена на {newEmail}",
|
||||
"authenticationSuccessful": "Аўтэнтыфікацыя паспяхова пройдзена!",
|
||||
"incorrectRecoveryKey": "Няправільны ключ аднаўлення",
|
||||
"enterPassword": "Увядзіце пароль",
|
||||
"selectExportFormat": "Выберыце фармат экспартавання",
|
||||
"exportDialogDesc": "Зашыфраванае экспартаванне будзе абаронена паролем, які вы выберыце.",
|
||||
@@ -287,18 +249,10 @@
|
||||
"focusOnSearchBar": "Сфакусіравацца на пошуку пры запуску праграмы",
|
||||
"confirmUpdatingkey": "Вы сапраўды хочаце абнавіць сакрэтны ключ?",
|
||||
"minimizeAppOnCopy": "Згортваць праграму пры капіяванні",
|
||||
"editCodeAuthMessage": "Прайдзіце аўтэнтыфікацыю, каб рэдагаваць код",
|
||||
"deleteCodeAuthMessage": "Прайдзіце аўтэнтыфікацыю, каб выдаліць код",
|
||||
"showQRAuthMessage": "Прайдзіце аўтэнтыфікацыю, каб паказаць QR-код",
|
||||
"confirmAccountDeleteTitle": "Пацвердзіце выдаленне ўліковага запісу",
|
||||
"androidBiometricHint": "Праверыць ідэнтыфікацыю",
|
||||
"@androidBiometricHint": {
|
||||
"description": "Hint message advising the user how to authenticate with biometrics. It is used on Android side. Maximum 60 characters."
|
||||
},
|
||||
"androidBiometricNotRecognized": "Не распазнана. Паспрабуйце яшчэ раз.",
|
||||
"@androidBiometricNotRecognized": {
|
||||
"description": "Message to let the user know that authentication was failed. It is used on Android side. Maximum 60 characters."
|
||||
},
|
||||
"androidBiometricSuccess": "Паспяхова",
|
||||
"@androidBiometricSuccess": {
|
||||
"description": "Message to let the user know that authentication was successful. It is used on Android side. Maximum 60 characters."
|
||||
@@ -307,22 +261,6 @@
|
||||
"@androidCancelButton": {
|
||||
"description": "Message showed on a button that the user can click to leave the current dialog. It is used on Android side. Maximum 30 characters."
|
||||
},
|
||||
"androidSignInTitle": "Патрабуецца аўтэнтыфікацыя",
|
||||
"@androidSignInTitle": {
|
||||
"description": "Message showed as a title in a dialog which indicates the user that they need to scan biometric to continue. It is used on Android side. Maximum 60 characters."
|
||||
},
|
||||
"androidBiometricRequiredTitle": "Патрабуецца біяметрыя",
|
||||
"@androidBiometricRequiredTitle": {
|
||||
"description": "Message showed as a title in a dialog which indicates the user has not set up biometric authentication on their device. It is used on Android side. Maximum 60 characters."
|
||||
},
|
||||
"androidDeviceCredentialsRequiredTitle": "Патрабуюцца ўліковыя даныя прылады",
|
||||
"@androidDeviceCredentialsRequiredTitle": {
|
||||
"description": "Message showed as a title in a dialog which indicates the user has not set up credentials authentication on their device. It is used on Android side. Maximum 60 characters."
|
||||
},
|
||||
"androidDeviceCredentialsSetupDescription": "Патрабуюцца ўліковыя даныя прылады",
|
||||
"@androidDeviceCredentialsSetupDescription": {
|
||||
"description": "Message advising the user to go to the settings and configure device credentials on their device. It shows in a dialog on Android side."
|
||||
},
|
||||
"goToSettings": "Перайсці ў налады",
|
||||
"@goToSettings": {
|
||||
"description": "Message showed on a button that the user can click to go to settings pages from the current dialog. It is used on both Android and iOS side. Maximum 30 characters."
|
||||
@@ -331,24 +269,11 @@
|
||||
"@iOSOkButton": {
|
||||
"description": "Message showed on a button that the user can click to leave the current dialog. It is used on iOS side. Maximum 30 characters."
|
||||
},
|
||||
"noInternetConnection": "Адсутнічае падключэнне да інтэрнэту",
|
||||
"signOutFromOtherDevices": "Выйсці з іншых прылад",
|
||||
"signOutOtherDevices": "Выйсці на іншых прыладах",
|
||||
"doNotSignOut": "Не выходзіць",
|
||||
"waitingForBrowserRequest": "Чаканне запыту браўзера...",
|
||||
"waitingForVerification": "Чаканне праверкі...",
|
||||
"passkey": "Ключ доступу",
|
||||
"passKeyPendingVerification": "Праверка пакуль яшчэ не завершана",
|
||||
"loginSessionExpired": "Сеанс завяршыўся",
|
||||
"developerSettings": "Налады распрацоўшчыка",
|
||||
"serverEndpoint": "Канцавы пункт сервера",
|
||||
"invalidEndpoint": "Памылковы канцавы пункт",
|
||||
"endpointUpdatedMessage": "Канцавы пункт паспяхова абноўлены",
|
||||
"customEndpoint": "Падключана да {endpoint}",
|
||||
"pinText": "Замацаваць",
|
||||
"unpinText": "Адмацаваць",
|
||||
"pinnedCodeMessage": "{code} быў замацаваны",
|
||||
"unpinnedCodeMessage": "{code} быў адмацаваны",
|
||||
"pinned": "Замацавана",
|
||||
"tags": "Тэгі",
|
||||
"createNewTag": "Стварыць новы тэг",
|
||||
@@ -356,38 +281,23 @@
|
||||
"create": "Стварыць",
|
||||
"editTag": "Рэдагаванне тэг",
|
||||
"deleteTagTitle": "Выдаліць тэг?",
|
||||
"updateNotAvailable": "Абнаўленне недаступна",
|
||||
"viewRawCodes": "Паглядзець неапрацаваныя коды",
|
||||
"rawCodes": "Неапрацаваныя коды",
|
||||
"rawCodeData": "Неапрацаваныя даныя кода",
|
||||
"appLock": "Блакіроўка праграмы",
|
||||
"noSystemLockFound": "Сістэма блакіроўкі не знойдзена",
|
||||
"autoLock": "Аўтаблакіроўка",
|
||||
"immediately": "Адразу",
|
||||
"reEnterPassword": "Увядзіце пароль паўторна",
|
||||
"reEnterPin": "Увядзіце PIN-код яшчэ раз",
|
||||
"next": "Далей",
|
||||
"tooManyIncorrectAttempts": "Занадта шмат няўдалых спроб",
|
||||
"tapToUnlock": "Націсніце для разблакіроўкі",
|
||||
"setNewPassword": "Задаць новы пароль",
|
||||
"deviceLock": "Блакіроўка прылады",
|
||||
"hideContent": "Схаваць змест",
|
||||
"pinLock": "Блакіроўка PIN'ам",
|
||||
"enterPin": "Увядзіце PIN-код",
|
||||
"setNewPin": "Задаць новы PIN",
|
||||
"appLockNotEnabled": "Блакіроўка праграмы не ўключана",
|
||||
"duplicateCodes": "Дублікаты кадоў",
|
||||
"noDuplicates": "✨ Няма дублікатаў",
|
||||
"deduplicateCodes": "Дубліраваныя кады",
|
||||
"deselectAll": "Зняць выбар з усіх",
|
||||
"selectAll": "Выбраць усе",
|
||||
"deleteDuplicates": "Выдаліць дублікаты",
|
||||
"plainHTML": "Звычайны HTML",
|
||||
"tellUsWhatYouThink": "Раскажыце, што вы думаеце",
|
||||
"dropReviewiOS": "Пакіньце водгук у App Store",
|
||||
"dropReviewAndroid": "Пакіньце водгук у Play Store",
|
||||
"giveUsAStarOnGithub": "Адзначце нас зоркай на Github",
|
||||
"loginWithAuthAccount": "Увайдзіце з дапамогай уліковага запісу Auth",
|
||||
"advanced": "Пашыраныя",
|
||||
"algorithm": "Алгарытм",
|
||||
"type": "Тып",
|
||||
|
||||
@@ -173,7 +173,6 @@
|
||||
"invalidQRCode": "Código QR no válido",
|
||||
"noRecoveryKeyTitle": "¿No tienes la clave de recuperación?",
|
||||
"enterEmailHint": "Introduce tu dirección de correo electrónico",
|
||||
"enterNewEmailHint": "Introduce tu nueva dirección de correo electrónico",
|
||||
"invalidEmailTitle": "Dirección de correo electrónico no válida",
|
||||
"invalidEmailMessage": "Por favor, introduce una dirección de correo electrónico válida.",
|
||||
"deleteAccount": "Eliminar cuenta",
|
||||
@@ -514,10 +513,5 @@
|
||||
"free5GB": "5 GB gratis en <bold-green>ente</bold-green> Fotos",
|
||||
"loginWithAuthAccount": "Inicia sesión con tu cuenta de Auth",
|
||||
"freeStorageOffer": "10% de descuento en <bold-green>ente</bold-green> fotos",
|
||||
"freeStorageOfferDescription": "Usa el cupón \"AUTH\" para obtener un 10% de descuento en el primer año",
|
||||
"advanced": "Avanzado",
|
||||
"algorithm": "Algoritmo",
|
||||
"type": "Tipo",
|
||||
"period": "Periodo",
|
||||
"digits": "Dígitos"
|
||||
"freeStorageOfferDescription": "Usa el cupón \"AUTH\" para obtener un 10% de descuento en el primer año"
|
||||
}
|
||||
@@ -11,7 +11,6 @@
|
||||
"setupFirstAccount": "Lisa oma esimene kasutajakonto",
|
||||
"importScanQrCode": "Skanneeri QR-koodi",
|
||||
"qrCode": "QR-kood",
|
||||
"importEnterSetupKey": "Sisesta seadistusvõti",
|
||||
"importAccountPageTitle": "Sisesta kasutajakonto üksikasjad",
|
||||
"secretCanNotBeEmpty": "Saladus ei tohi jääda tühjaks",
|
||||
"bothIssuerAndAccountCanNotBeEmpty": "Nii kasutajakonto kui väljaandja ei tohi tühjaks jääda",
|
||||
@@ -33,7 +32,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"codeAccountHint": "Kasutajakonto (sina@domeen.com)",
|
||||
"codeTagHint": "Silt",
|
||||
"accountKeyType": "Võtme tüüp",
|
||||
"sessionExpired": "Sessioon on aegunud",
|
||||
@@ -42,12 +40,7 @@
|
||||
},
|
||||
"pleaseLoginAgain": "Palun logi uuesti sisse",
|
||||
"loggingOut": "Väljalogimine...",
|
||||
"timeBasedKeyType": "Ajapõhine (TOTP)",
|
||||
"counterBasedKeyType": "Loenduripõhine (HOTP)",
|
||||
"saveAction": "Salvesta",
|
||||
"nextTotpTitle": "järgmine",
|
||||
"deleteCodeTitle": "Kas kustutame koodi?",
|
||||
"deleteCodeMessage": "Kas sa oled kindel, et soovid selle koodi kustutada? Seda tegevust ei saa tagasi pöörata.",
|
||||
"trash": "Prügikast",
|
||||
"viewLogsAction": "Vaata logisid",
|
||||
"preparingLogsTitle": "Valmistan logisid ette...",
|
||||
@@ -63,18 +56,7 @@
|
||||
"copyEmailAction": "Kopeeri e-posti aadress",
|
||||
"exportLogsAction": "Ekspordi logid",
|
||||
"reportABug": "Teata veast",
|
||||
"crashAndErrorReporting": "Teatamine vigadest ja kokkujooksmistest",
|
||||
"reportBug": "Teata veast",
|
||||
"emailUsMessage": "Saada meile e-kiri aadressile {email}",
|
||||
"@emailUsMessage": {
|
||||
"placeholders": {
|
||||
"email": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"contactSupport": "Võta ühendust klienditoega",
|
||||
"rateUsOnStore": "Arvusta meid rakendustepoes: {storeName}",
|
||||
"contactSupport": "Võtke ühendust klienditoega",
|
||||
"blog": "Blogi",
|
||||
"verifyPassword": "Korda salasõna",
|
||||
"pleaseWait": "Palun oota...",
|
||||
@@ -88,13 +70,8 @@
|
||||
"changeEmail": "Muuda e-posti aadressi",
|
||||
"changePassword": "Muuda salasõna",
|
||||
"data": "Andmed",
|
||||
"importCodes": "Impordi koode",
|
||||
"importTypePlainText": "Votmindamata tekstina",
|
||||
"importTypeEnteEncrypted": "Ente krüptitud ekspordina",
|
||||
"passwordForDecryptingExport": "Salasõna eksporditud andmete dekrüptimiseks",
|
||||
"passwordEmptyError": "Salasõna väli ei saa olla tühi",
|
||||
"importFromApp": "Impordi koodid rakendusest {appName}",
|
||||
"selectFile": "Vali fail",
|
||||
"ok": "Sobib",
|
||||
"cancel": "Katkesta",
|
||||
"yes": "Jah",
|
||||
|
||||
@@ -506,7 +506,7 @@
|
||||
"selectAll": "Chọn tất cả",
|
||||
"deleteDuplicates": "Xóa trùng lặp",
|
||||
"plainHTML": "HTML thuần",
|
||||
"tellUsWhatYouThink": "Cho biết bạn nghĩ gì",
|
||||
"tellUsWhatYouThink": "Hãy cho chúng tôi biết bạn nghĩ gì",
|
||||
"dropReviewiOS": "Đánh giá ngay trên App Store",
|
||||
"dropReviewAndroid": "Đánh giá ngay trên Play Store",
|
||||
"supportEnte": "Hỗ trợ <bold-green>ente</bold-green>",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import "package:ente_auth/l10n/arb/app_localizations.dart"
|
||||
show AppLocalizations;
|
||||
import "package:flutter/widgets.dart";
|
||||
export "package:ente_auth/l10n/arb/app_localizations.dart"
|
||||
show AppLocalizations;
|
||||
import "package:flutter_gen/gen_l10n/app_localizations.dart";
|
||||
|
||||
export "package:flutter_gen/gen_l10n/app_localizations.dart";
|
||||
|
||||
extension AppLocalizationsX on BuildContext {
|
||||
AppLocalizations get l10n => AppLocalizations.of(this);
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'dart:convert';
|
||||
|
||||
class BillingPlans {
|
||||
final List<BillingPlan> plans;
|
||||
final FreePlan? freePlan;
|
||||
final FreePlan freePlan;
|
||||
|
||||
BillingPlans({
|
||||
required this.plans,
|
||||
@@ -12,12 +12,12 @@ class BillingPlans {
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'plans': plans.map((x) => x.toMap()).toList(),
|
||||
'freePlan': freePlan?.toMap(),
|
||||
'freePlan': freePlan.toMap(),
|
||||
};
|
||||
}
|
||||
|
||||
static BillingPlans fromMap(Map<String, dynamic>? map) {
|
||||
if (map == null) return BillingPlans(plans: [], freePlan: null);
|
||||
static fromMap(Map<String, dynamic>? map) {
|
||||
if (map == null) return null;
|
||||
|
||||
return BillingPlans(
|
||||
plans: List<BillingPlan>.from(
|
||||
@@ -49,7 +49,7 @@ class FreePlan {
|
||||
};
|
||||
}
|
||||
|
||||
static FreePlan? fromMap(Map<String, dynamic>? map) {
|
||||
static fromMap(Map<String, dynamic>? map) {
|
||||
if (map == null) return null;
|
||||
|
||||
return FreePlan(
|
||||
@@ -91,7 +91,7 @@ class BillingPlan {
|
||||
};
|
||||
}
|
||||
|
||||
static BillingPlan? fromMap(Map<String, dynamic>? map) {
|
||||
static fromMap(Map<String, dynamic>? map) {
|
||||
if (map == null) return null;
|
||||
|
||||
return BillingPlan(
|
||||
|
||||
@@ -332,7 +332,7 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
|
||||
},
|
||||
);
|
||||
},
|
||||
barrierColor: Colors.black.withValues(alpha: 0.85),
|
||||
barrierColor: Colors.black.withOpacity(0.85),
|
||||
barrierDismissible: false,
|
||||
);
|
||||
},
|
||||
|
||||
@@ -75,7 +75,7 @@ class CodeDisplayStore {
|
||||
builder: (BuildContext context) {
|
||||
return EditTagDialog(tag: tag);
|
||||
},
|
||||
barrierColor: Colors.black.withValues(alpha: 0.85),
|
||||
barrierColor: Colors.black.withOpacity(0.85),
|
||||
barrierDismissible: false,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -147,13 +147,12 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
|
||||
),
|
||||
),
|
||||
child: DottedBorder(
|
||||
options: const RoundedRectDottedBorderOptions(
|
||||
padding: EdgeInsets.zero,
|
||||
strokeWidth: 1,
|
||||
color: Color(0xFF6B6B6B),
|
||||
dashPattern: [6, 6],
|
||||
radius: Radius.circular(8),
|
||||
),
|
||||
padding: EdgeInsets.zero,
|
||||
borderType: BorderType.RRect,
|
||||
strokeWidth: 1,
|
||||
color: const Color(0xFF6B6B6B),
|
||||
dashPattern: const [6, 6],
|
||||
radius: const Radius.circular(8),
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
child: Stack(
|
||||
@@ -315,13 +314,7 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
|
||||
await _recoveryKeyFile.delete();
|
||||
}
|
||||
_recoveryKeyFile.writeAsStringSync(recoveryKey);
|
||||
await SharePlus.instance.share(
|
||||
ShareParams(
|
||||
files: [
|
||||
XFile(_recoveryKeyFile.path),
|
||||
],
|
||||
),
|
||||
);
|
||||
await Share.shareXFiles([XFile(_recoveryKeyFile.path)]);
|
||||
Future.delayed(const Duration(milliseconds: 500), () {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
|
||||
@@ -82,7 +82,7 @@ class _SessionsPageState extends State<SessionsPage> {
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface
|
||||
.withValues(alpha: 0.8),
|
||||
.withOpacity(0.8),
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
@@ -95,7 +95,7 @@ class _SessionsPageState extends State<SessionsPage> {
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface
|
||||
.withValues(alpha: 0.8),
|
||||
.withOpacity(0.8),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -54,12 +54,12 @@ class BannerWidget extends StatelessWidget {
|
||||
dashColor = const Color.fromRGBO(255, 191, 12, 1);
|
||||
boxShadow = [
|
||||
BoxShadow(
|
||||
color: const Color(0xFFFDB816).withValues(alpha: 0.1),
|
||||
color: const Color(0xFFFDB816).withOpacity(0.1),
|
||||
blurRadius: 50,
|
||||
spreadRadius: 80,
|
||||
),
|
||||
BoxShadow(
|
||||
color: const Color(0xFFFDB816).withValues(alpha: 0.2),
|
||||
color: const Color(0xFFFDB816).withOpacity(0.2),
|
||||
blurRadius: 25,
|
||||
),
|
||||
];
|
||||
@@ -71,13 +71,12 @@ class BannerWidget extends StatelessWidget {
|
||||
dashColor = const Color.fromRGBO(233, 233, 233, 1);
|
||||
boxShadow = [
|
||||
BoxShadow(
|
||||
color: const Color.fromRGBO(78, 78, 78, 1).withValues(alpha: 0.2),
|
||||
color: const Color.fromRGBO(78, 78, 78, 1).withOpacity(0.2),
|
||||
blurRadius: 50,
|
||||
spreadRadius: 100,
|
||||
),
|
||||
BoxShadow(
|
||||
color:
|
||||
const Color.fromRGBO(23, 22, 22, 0.30).withValues(alpha: 0.1),
|
||||
color: const Color.fromRGBO(23, 22, 22, 0.30).withOpacity(0.1),
|
||||
blurRadius: 25,
|
||||
),
|
||||
];
|
||||
@@ -88,12 +87,12 @@ class BannerWidget extends StatelessWidget {
|
||||
dashColor = const Color.fromRGBO(29, 185, 84, 1);
|
||||
boxShadow = [
|
||||
BoxShadow(
|
||||
color: const Color.fromRGBO(38, 203, 95, 1).withValues(alpha: 0.08),
|
||||
color: const Color.fromRGBO(38, 203, 95, 1).withOpacity(0.08),
|
||||
blurRadius: 50,
|
||||
spreadRadius: 100,
|
||||
),
|
||||
BoxShadow(
|
||||
color: const Color.fromRGBO(0, 0, 0, 0.50).withValues(alpha: 0.08),
|
||||
color: const Color.fromRGBO(0, 0, 0, 0.50).withOpacity(0.08),
|
||||
blurRadius: 25,
|
||||
),
|
||||
];
|
||||
@@ -104,12 +103,12 @@ class BannerWidget extends StatelessWidget {
|
||||
imagePath = "assets/discount.png";
|
||||
boxShadow = [
|
||||
BoxShadow(
|
||||
color: const Color.fromRGBO(38, 203, 95, 1).withValues(alpha: 0.08),
|
||||
color: const Color.fromRGBO(38, 203, 95, 1).withOpacity(0.08),
|
||||
blurRadius: 50,
|
||||
spreadRadius: 100,
|
||||
),
|
||||
BoxShadow(
|
||||
color: const Color.fromRGBO(0, 0, 0, 0.50).withValues(alpha: 0.08),
|
||||
color: const Color.fromRGBO(0, 0, 0, 0.50).withOpacity(0.08),
|
||||
blurRadius: 25,
|
||||
),
|
||||
];
|
||||
@@ -122,11 +121,10 @@ class BannerWidget extends StatelessWidget {
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(50)),
|
||||
child: DottedBorder(
|
||||
options: RoundedRectDottedBorderOptions(
|
||||
radius: const Radius.circular(50),
|
||||
dashPattern: <double>[3, 3],
|
||||
color: dashColor,
|
||||
),
|
||||
borderType: BorderType.RRect,
|
||||
radius: const Radius.circular(50),
|
||||
dashPattern: const <double>[3, 3],
|
||||
color: dashColor,
|
||||
child: Stack(
|
||||
children: [
|
||||
if (BannerType.starUs == type)
|
||||
|
||||
@@ -28,7 +28,7 @@ class CustomIconWidget extends StatelessWidget {
|
||||
width: 1.5,
|
||||
color: getEnteColorScheme(context)
|
||||
.tagChipSelectedColor
|
||||
.withValues(alpha: 0.5),
|
||||
.withOpacity(0.5),
|
||||
),
|
||||
borderRadius: SmoothBorderRadius(
|
||||
cornerRadius: 15.5,
|
||||
@@ -102,7 +102,7 @@ class CustomIconWidget extends StatelessWidget {
|
||||
child: Icon(
|
||||
Icons.edit,
|
||||
size: 16,
|
||||
color: Colors.black.withValues(alpha: 0.9),
|
||||
color: Colors.black.withOpacity(0.9),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -52,7 +52,7 @@ class NotificationWidget extends StatelessWidget {
|
||||
subTextStyle = textTheme.miniMuted;
|
||||
strokeColorScheme = colorScheme;
|
||||
boxShadow = [
|
||||
BoxShadow(color: Colors.black.withValues(alpha: 0.25), blurRadius: 1),
|
||||
BoxShadow(color: Colors.black.withOpacity(0.25), blurRadius: 1),
|
||||
];
|
||||
break;
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ class TitleBarWidget extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> _actionsWithPaddingInBetween() {
|
||||
_actionsWithPaddingInBetween() {
|
||||
if (actionIcons == null) {
|
||||
return <Widget>[const SizedBox.shrink()];
|
||||
}
|
||||
@@ -135,7 +135,7 @@ class TitleBarWidget extends StatelessWidget {
|
||||
return <Widget>[const SizedBox.shrink()];
|
||||
}
|
||||
if (length == 1) {
|
||||
return actionIcons!;
|
||||
return actionIcons;
|
||||
}
|
||||
while (index < length) {
|
||||
if (!addWhiteSpace) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:ente_auth/ente_theme_data.dart';
|
||||
import 'package:ente_auth/models/execution_states.dart';
|
||||
import 'package:ente_auth/models/typedefs.dart';
|
||||
import 'package:ente_auth/theme/colors.dart';
|
||||
import 'package:ente_auth/ui/common/loading_widget.dart';
|
||||
import 'package:ente_auth/utils/debouncer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -105,7 +104,7 @@ class _ToggleSwitchWidgetState extends State<ToggleSwitchWidget> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _stateIcon(EnteColorScheme enteColorScheme) {
|
||||
Widget _stateIcon(enteColorScheme) {
|
||||
if (executionState == ExecutionState.idle) {
|
||||
return const SizedBox(width: 24);
|
||||
} else if (executionState == ExecutionState.inProgress) {
|
||||
|
||||
@@ -23,8 +23,7 @@ class CoachMarkWidget extends StatelessWidget {
|
||||
Expanded(
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
color:
|
||||
Theme.of(context).colorScheme.surface.withValues(alpha: 0.1),
|
||||
color: Theme.of(context).colorScheme.surface.withOpacity(0.1),
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: 8, sigmaY: 8),
|
||||
child: Row(
|
||||
|
||||
@@ -77,7 +77,7 @@ class AboutSectionWidget extends StatelessWidget {
|
||||
UpdateService.instance.getLatestVersionInfo(),
|
||||
);
|
||||
},
|
||||
barrierColor: Colors.black.withValues(alpha: 0.85),
|
||||
barrierColor: Colors.black.withOpacity(0.85),
|
||||
);
|
||||
} else {
|
||||
showShortToast(
|
||||
|
||||
@@ -56,7 +56,7 @@ class AccountSectionWidget extends StatelessWidget {
|
||||
builder: (BuildContext context) {
|
||||
return const ChangeEmailDialog();
|
||||
},
|
||||
barrierColor: Colors.black.withValues(alpha: 0.85),
|
||||
barrierColor: Colors.black.withOpacity(0.85),
|
||||
barrierDismissible: false,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ class _DuplicateCodePageState extends State<DuplicateCodePage> {
|
||||
color: Theme.of(context)
|
||||
.iconTheme
|
||||
.color!
|
||||
.withValues(alpha: 0.7),
|
||||
.withOpacity(0.7),
|
||||
),
|
||||
),
|
||||
const Padding(padding: EdgeInsets.only(left: 4)),
|
||||
|
||||
@@ -170,14 +170,9 @@ Future<void> _exportCodes(
|
||||
}
|
||||
codeFile.writeAsStringSync(fileContent);
|
||||
final Size size = MediaQuery.of(context).size;
|
||||
await SharePlus.instance.share(
|
||||
ShareParams(
|
||||
files: <XFile>[
|
||||
XFile(codeFile.path, mimeType: 'text/plain'),
|
||||
],
|
||||
sharePositionOrigin:
|
||||
Rect.fromLTWH(0, 0, size.width, size.height / 2),
|
||||
),
|
||||
await Share.shareXFiles(
|
||||
[XFile(codeFile.path)],
|
||||
sharePositionOrigin: Rect.fromLTWH(0, 0, size.width, size.height / 2),
|
||||
);
|
||||
Future.delayed(const Duration(seconds: 30), () async {
|
||||
if (codeFile.existsSync()) {
|
||||
|
||||
@@ -116,10 +116,10 @@ class _LockScreenConfirmPasswordState extends State<LockScreenConfirmPassword> {
|
||||
shape: BoxShape.circle,
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Colors.grey.shade500.withValues(alpha: 0.2),
|
||||
Colors.grey.shade50.withValues(alpha: 0.1),
|
||||
Colors.grey.shade400.withValues(alpha: 0.2),
|
||||
Colors.grey.shade300.withValues(alpha: 0.4),
|
||||
Colors.grey.shade500.withOpacity(0.2),
|
||||
Colors.grey.shade50.withOpacity(0.1),
|
||||
Colors.grey.shade400.withOpacity(0.2),
|
||||
Colors.grey.shade300.withOpacity(0.4),
|
||||
],
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import "dart:io";
|
||||
|
||||
import "package:ente_auth/l10n/l10n.dart";
|
||||
import "package:ente_auth/theme/colors.dart";
|
||||
import "package:ente_auth/theme/ente_theme.dart";
|
||||
import "package:ente_auth/theme/text_style.dart";
|
||||
import "package:ente_auth/ui/settings/lock_screen/custom_pin_keypad.dart";
|
||||
import "package:ente_auth/utils/lock_screen_settings.dart";
|
||||
import "package:flutter/material.dart";
|
||||
@@ -91,7 +89,7 @@ class _LockScreenConfirmPinState extends State<LockScreenConfirmPin> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _getBody(EnteColorScheme colorTheme, EnteTextTheme textTheme) {
|
||||
Widget _getBody(colorTheme, textTheme) {
|
||||
return Center(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
@@ -109,10 +107,10 @@ class _LockScreenConfirmPinState extends State<LockScreenConfirmPin> {
|
||||
shape: BoxShape.circle,
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Colors.grey.shade500.withValues(alpha: 0.2),
|
||||
Colors.grey.shade50.withValues(alpha: 0.1),
|
||||
Colors.grey.shade400.withValues(alpha: 0.2),
|
||||
Colors.grey.shade300.withValues(alpha: 0.4),
|
||||
Colors.grey.shade500.withOpacity(0.2),
|
||||
Colors.grey.shade50.withOpacity(0.1),
|
||||
Colors.grey.shade400.withOpacity(0.2),
|
||||
Colors.grey.shade300.withOpacity(0.4),
|
||||
],
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
|
||||
@@ -127,10 +127,10 @@ class _LockScreenPasswordState extends State<LockScreenPassword> {
|
||||
shape: BoxShape.circle,
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Colors.grey.shade500.withValues(alpha: 0.2),
|
||||
Colors.grey.shade50.withValues(alpha: 0.1),
|
||||
Colors.grey.shade400.withValues(alpha: 0.2),
|
||||
Colors.grey.shade300.withValues(alpha: 0.4),
|
||||
Colors.grey.shade500.withOpacity(0.2),
|
||||
Colors.grey.shade50.withOpacity(0.1),
|
||||
Colors.grey.shade400.withOpacity(0.2),
|
||||
Colors.grey.shade300.withOpacity(0.4),
|
||||
],
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
|
||||
@@ -178,10 +178,10 @@ class _LockScreenPinState extends State<LockScreenPin> {
|
||||
shape: BoxShape.circle,
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Colors.grey.shade500.withValues(alpha: 0.2),
|
||||
Colors.grey.shade50.withValues(alpha: 0.1),
|
||||
Colors.grey.shade400.withValues(alpha: 0.2),
|
||||
Colors.grey.shade300.withValues(alpha: 0.4),
|
||||
Colors.grey.shade500.withOpacity(0.2),
|
||||
Colors.grey.shade50.withOpacity(0.1),
|
||||
Colors.grey.shade400.withOpacity(0.2),
|
||||
Colors.grey.shade300.withOpacity(0.4),
|
||||
],
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
|
||||
@@ -43,7 +43,7 @@ class _SupportSectionWidgetState extends State<SupportSectionWidget> {
|
||||
trailingIconIsMuted: true,
|
||||
onTap: () async {
|
||||
try {
|
||||
await PlatformUtil.openWebView(
|
||||
PlatformUtil.openWebView(
|
||||
context,
|
||||
context.l10n.faq,
|
||||
"https://help.ente.io/auth/faq",
|
||||
|
||||
@@ -35,7 +35,7 @@ class SortCodeMenuWidget extends StatelessWidget {
|
||||
text,
|
||||
style: Theme.of(context).textTheme.titleMedium!.copyWith(
|
||||
fontSize: 14,
|
||||
color: Theme.of(context).iconTheme.color!.withValues(alpha: 0.7),
|
||||
color: Theme.of(context).iconTheme.color!.withOpacity(0.7),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:ente_auth/l10n/l10n.dart';
|
||||
import 'package:ente_auth/locale.dart';
|
||||
import 'package:ente_auth/utils/lock_screen_settings.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
/// A widget which handles app lifecycle events for showing and hiding a lock screen.
|
||||
/// This should wrap around a `MyApp` widget (or equivalent).
|
||||
|
||||
@@ -96,10 +96,10 @@ class _LockScreenState extends State<LockScreen> with WidgetsBindingObserver {
|
||||
shape: BoxShape.circle,
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Colors.grey.shade500.withValues(alpha: 0.2),
|
||||
Colors.grey.shade50.withValues(alpha: 0.1),
|
||||
Colors.grey.shade400.withValues(alpha: 0.2),
|
||||
Colors.grey.shade300.withValues(alpha: 0.4),
|
||||
Colors.grey.shade500.withOpacity(0.2),
|
||||
Colors.grey.shade50.withOpacity(0.1),
|
||||
Colors.grey.shade400.withOpacity(0.2),
|
||||
Colors.grey.shade300.withOpacity(0.4),
|
||||
],
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
|
||||
@@ -98,9 +98,8 @@ class _TwoFactorRecoveryPageState extends State<TwoFactorRecoveryPage> {
|
||||
style: TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
fontSize: 12,
|
||||
color: getEnteColorScheme(context)
|
||||
.textBase
|
||||
.withValues(alpha: 0.9),
|
||||
color:
|
||||
getEnteColorScheme(context).textBase.withOpacity(0.9),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -180,7 +180,7 @@ Future<ButtonResult?> showGenericErrorDialog({
|
||||
context,
|
||||
context.l10n.faq,
|
||||
"https://help.ente.io/auth/troubleshooting/windows-login",
|
||||
).ignore();
|
||||
);
|
||||
},
|
||||
),
|
||||
ButtonWidget(
|
||||
|
||||
@@ -34,7 +34,7 @@ class DirectoryUtils {
|
||||
}
|
||||
|
||||
static String migratedNamingChanges = "migrated_naming_changes.b5";
|
||||
static Future<void> migrateNamingChanges() async {
|
||||
static migrateNamingChanges() async {
|
||||
try {
|
||||
final sharedPrefs = await SharedPreferences.getInstance();
|
||||
if (sharedPrefs.containsKey(migratedNamingChanges)) {
|
||||
@@ -57,7 +57,7 @@ class DirectoryUtils {
|
||||
Directory oldDataDir;
|
||||
Directory newDataDir = await getApplicationSupportDirectory();
|
||||
await newDataDir.create(recursive: true);
|
||||
|
||||
|
||||
if (Platform.isLinux) {
|
||||
oldDataDir = Directory(
|
||||
p.join(dataHome.path, "ente_auth"),
|
||||
|
||||
@@ -232,13 +232,9 @@ Future<void> exportLogs(
|
||||
MimeType.zip,
|
||||
);
|
||||
} else {
|
||||
await SharePlus.instance.share(
|
||||
ShareParams(
|
||||
files: <XFile>[
|
||||
XFile(zipFilePath, mimeType: 'application/zip'),
|
||||
],
|
||||
sharePositionOrigin: Rect.fromLTWH(0, 0, size.width, size.height / 2),
|
||||
),
|
||||
await Share.shareXFiles(
|
||||
[XFile(zipFilePath, mimeType: 'application/zip')],
|
||||
sharePositionOrigin: Rect.fromLTWH(0, 0, size.width, size.height / 2),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,11 +28,7 @@ class PlatformUtil {
|
||||
? cupertinoTextSelectionControls
|
||||
: desktopTextSelectionControls;
|
||||
|
||||
static Future<void> openWebView(
|
||||
BuildContext context,
|
||||
String title,
|
||||
String url,
|
||||
) async {
|
||||
static openWebView(BuildContext context, String title, String url) async {
|
||||
if (PlatformUtil.isDesktop()) {
|
||||
await launchUrlString(url);
|
||||
return;
|
||||
|
||||
@@ -91,11 +91,9 @@ Future<ShareResult> shareText(
|
||||
}) async {
|
||||
try {
|
||||
final sharePosOrigin = _sharePosOrigin(context, key);
|
||||
return SharePlus.instance.share(
|
||||
ShareParams(
|
||||
text: text,
|
||||
sharePositionOrigin: sharePosOrigin,
|
||||
),
|
||||
return Share.share(
|
||||
text,
|
||||
sharePositionOrigin: sharePosOrigin,
|
||||
);
|
||||
} catch (e, s) {
|
||||
Logger("ShareUtil").severe("failed to share text", e, s);
|
||||
|
||||
@@ -47,6 +47,6 @@ void showToast(
|
||||
}
|
||||
}
|
||||
|
||||
void showShortToast(BuildContext context, String message) {
|
||||
void showShortToast(context, String message) {
|
||||
showToast(context, message, toastLength: Toast.LENGTH_SHORT);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ class WindowsProtocolHandler {
|
||||
hKey,
|
||||
txtKey,
|
||||
txtValue,
|
||||
REG_SZ,
|
||||
REG_VALUE_TYPE.REG_SZ,
|
||||
txtData,
|
||||
txtData.length * 2 + 2,
|
||||
);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <flutter_local_authentication/flutter_local_authentication_plugin.h>
|
||||
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
|
||||
#include <gtk/gtk_plugin.h>
|
||||
#include <screen_retriever_linux/screen_retriever_linux_plugin.h>
|
||||
#include <screen_retriever/screen_retriever_plugin.h>
|
||||
#include <sentry_flutter/sentry_flutter_plugin.h>
|
||||
#include <sodium_libs/sodium_libs_plugin.h>
|
||||
#include <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h>
|
||||
@@ -31,9 +31,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) gtk_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "GtkPlugin");
|
||||
gtk_plugin_register_with_registrar(gtk_registrar);
|
||||
g_autoptr(FlPluginRegistrar) screen_retriever_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverLinuxPlugin");
|
||||
screen_retriever_linux_plugin_register_with_registrar(screen_retriever_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) screen_retriever_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin");
|
||||
screen_retriever_plugin_register_with_registrar(screen_retriever_registrar);
|
||||
g_autoptr(FlPluginRegistrar) sentry_flutter_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "SentryFlutterPlugin");
|
||||
sentry_flutter_plugin_register_with_registrar(sentry_flutter_registrar);
|
||||
|
||||
@@ -7,7 +7,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
||||
flutter_local_authentication
|
||||
flutter_secure_storage_linux
|
||||
gtk
|
||||
screen_retriever_linux
|
||||
screen_retriever
|
||||
sentry_flutter
|
||||
sodium_libs
|
||||
sqlite3_flutter_libs
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<releases>
|
||||
<release version="4.4.3" date="2025-06-21" />
|
||||
<release version="4.4.2" date="2025-06-21" />
|
||||
<release version="4.4.0" date="2025-05-31" />
|
||||
<release version="4.3.8" date="2025-05-20" />
|
||||
<release version="4.2.4" date="2025-01-11" />
|
||||
|
||||
@@ -8,7 +8,6 @@ import Foundation
|
||||
import app_links
|
||||
import connectivity_plus
|
||||
import device_info_plus
|
||||
import file_picker
|
||||
import file_saver
|
||||
import flutter_inappwebview_macos
|
||||
import flutter_local_authentication
|
||||
@@ -17,12 +16,12 @@ import flutter_secure_storage_macos
|
||||
import local_auth_darwin
|
||||
import package_info_plus
|
||||
import path_provider_foundation
|
||||
import screen_retriever_macos
|
||||
import screen_retriever
|
||||
import sentry_flutter
|
||||
import share_plus
|
||||
import shared_preferences_foundation
|
||||
import sodium_libs
|
||||
import sqflite_darwin
|
||||
import sqflite
|
||||
import sqlite3_flutter_libs
|
||||
import tray_manager
|
||||
import url_launcher_macos
|
||||
@@ -32,16 +31,15 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
AppLinksMacosPlugin.register(with: registry.registrar(forPlugin: "AppLinksMacosPlugin"))
|
||||
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
|
||||
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||
FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin"))
|
||||
FileSaverPlugin.register(with: registry.registrar(forPlugin: "FileSaverPlugin"))
|
||||
InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin"))
|
||||
FlutterLocalAuthenticationPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalAuthenticationPlugin"))
|
||||
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
|
||||
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
|
||||
LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin"))
|
||||
FLALocalAuthPlugin.register(with: registry.registrar(forPlugin: "FLALocalAuthPlugin"))
|
||||
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
ScreenRetrieverMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverMacosPlugin"))
|
||||
ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin"))
|
||||
SentryFlutterPlugin.register(with: registry.registrar(forPlugin: "SentryFlutterPlugin"))
|
||||
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
|
||||
@@ -2,14 +2,13 @@ PODS:
|
||||
- app_links (1.0.0):
|
||||
- FlutterMacOS
|
||||
- connectivity_plus (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- cupertino_http (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- device_info_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- file_picker (0.0.1):
|
||||
- FlutterMacOS
|
||||
- file_saver (0.0.1):
|
||||
- FlutterMacOS
|
||||
- flutter_inappwebview_macos (0.0.1):
|
||||
@@ -19,7 +18,7 @@ PODS:
|
||||
- FlutterMacOS
|
||||
- flutter_local_notifications (0.0.1):
|
||||
- FlutterMacOS
|
||||
- flutter_secure_storage_macos (6.1.3):
|
||||
- flutter_secure_storage_macos (6.1.1):
|
||||
- FlutterMacOS
|
||||
- FlutterMacOS (1.0.0)
|
||||
- local_auth_darwin (0.0.1):
|
||||
@@ -33,7 +32,7 @@ PODS:
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- screen_retriever_macos (0.0.1):
|
||||
- screen_retriever (0.0.1):
|
||||
- FlutterMacOS
|
||||
- Sentry/HybridSDK (8.46.0)
|
||||
- sentry_flutter (8.14.2):
|
||||
@@ -47,44 +46,39 @@ PODS:
|
||||
- FlutterMacOS
|
||||
- sodium_libs (2.2.1):
|
||||
- FlutterMacOS
|
||||
- sqflite_darwin (0.0.4):
|
||||
- sqflite (0.0.3):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- sqlite3 (3.50.1):
|
||||
- sqlite3/common (= 3.50.1)
|
||||
- sqlite3/common (3.50.1)
|
||||
- sqlite3/dbstatvtab (3.50.1):
|
||||
- "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.1):
|
||||
- "sqlite3/fts5 (3.46.1+1)":
|
||||
- sqlite3/common
|
||||
- sqlite3/math (3.50.1):
|
||||
- "sqlite3/perf-threadsafe (3.46.1+1)":
|
||||
- sqlite3/common
|
||||
- sqlite3/perf-threadsafe (3.50.1):
|
||||
- sqlite3/common
|
||||
- sqlite3/rtree (3.50.1):
|
||||
- "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
|
||||
- tray_manager (0.0.1):
|
||||
- FlutterMacOS
|
||||
- url_launcher_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- window_manager (0.5.0):
|
||||
- window_manager (0.2.0):
|
||||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
- app_links (from `Flutter/ephemeral/.symlinks/plugins/app_links/macos`)
|
||||
- connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`)
|
||||
- connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/darwin`)
|
||||
- cupertino_http (from `Flutter/ephemeral/.symlinks/plugins/cupertino_http/darwin`)
|
||||
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
|
||||
- file_picker (from `Flutter/ephemeral/.symlinks/plugins/file_picker/macos`)
|
||||
- file_saver (from `Flutter/ephemeral/.symlinks/plugins/file_saver/macos`)
|
||||
- flutter_inappwebview_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos`)
|
||||
- flutter_local_authentication (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_authentication/macos`)
|
||||
@@ -95,13 +89,13 @@ DEPENDENCIES:
|
||||
- objective_c (from `Flutter/ephemeral/.symlinks/plugins/objective_c/macos`)
|
||||
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
|
||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- screen_retriever_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos`)
|
||||
- screen_retriever (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos`)
|
||||
- sentry_flutter (from `Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos`)
|
||||
- share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`)
|
||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sodium_libs (from `Flutter/ephemeral/.symlinks/plugins/sodium_libs/macos`)
|
||||
- sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`)
|
||||
- sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin`)
|
||||
- sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`)
|
||||
- sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`)
|
||||
- tray_manager (from `Flutter/ephemeral/.symlinks/plugins/tray_manager/macos`)
|
||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||
- window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`)
|
||||
@@ -116,13 +110,11 @@ EXTERNAL SOURCES:
|
||||
app_links:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/app_links/macos
|
||||
connectivity_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/darwin
|
||||
cupertino_http:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/cupertino_http/darwin
|
||||
device_info_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos
|
||||
file_picker:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/file_picker/macos
|
||||
file_saver:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/file_saver/macos
|
||||
flutter_inappwebview_macos:
|
||||
@@ -143,8 +135,8 @@ EXTERNAL SOURCES:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
|
||||
path_provider_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
|
||||
screen_retriever_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos
|
||||
screen_retriever:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos
|
||||
sentry_flutter:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos
|
||||
share_plus:
|
||||
@@ -153,10 +145,10 @@ EXTERNAL SOURCES:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
||||
sodium_libs:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sodium_libs/macos
|
||||
sqflite_darwin:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin
|
||||
sqflite:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sqflite/darwin
|
||||
sqlite3_flutter_libs:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos
|
||||
tray_manager:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/tray_manager/macos
|
||||
url_launcher_macos:
|
||||
@@ -165,34 +157,33 @@ EXTERNAL SOURCES:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
app_links: afe860c55c7ef176cea7fb630a2b7d7736de591d
|
||||
connectivity_plus: 4adf20a405e25b42b9c9f87feff8f4b6fde18a4e
|
||||
app_links: 9028728e32c83a0831d9db8cf91c526d16cc5468
|
||||
connectivity_plus: 3f6c9057f4cd64198dc826edfb0542892f825343
|
||||
cupertino_http: 94ac07f5ff090b8effa6c5e2c47871d48ab7c86c
|
||||
device_info_plus: b0fafc687fb901e2af612763340f1b0d4352f8e5
|
||||
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
|
||||
file_saver: e35bd97de451dde55ff8c38862ed7ad0f3418d0f
|
||||
flutter_inappwebview_macos: c2d68649f9f8f1831bfcd98d73fd6256366d9d1d
|
||||
flutter_local_authentication: 2f9a2682f498abcc12d7e9729b5007a947170fdc
|
||||
flutter_local_notifications: 13862b132e32eb858dea558a86d45d08daeacfe7
|
||||
flutter_secure_storage_macos: 7f45e30f838cf2659862a4e4e3ee1c347c2b3b54
|
||||
flutter_local_notifications: 453432cd6399a07d072885bc7828fb2307868856
|
||||
flutter_secure_storage_macos: b2d62a774c23b060f0b99d0173b0b36abb4a8632
|
||||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||
local_auth_darwin: d2e8c53ef0c4f43c646462e3415432c4dab3ae19
|
||||
local_auth_darwin: 553ce4f9b16d3fdfeafce9cf042e7c9f77c1c391
|
||||
objective_c: ec13431e45ba099cb734eb2829a5c1cd37986cba
|
||||
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
|
||||
package_info_plus: f0052d280d17aa382b932f399edf32507174e870
|
||||
package_info_plus: a8a591e70e87ce97ce5d21b2594f69cea9e0312f
|
||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||
screen_retriever_macos: 452e51764a9e1cdb74b3c541238795849f21557f
|
||||
screen_retriever: 4f97c103641aab8ce183fa5af3b87029df167936
|
||||
Sentry: da60d980b197a46db0b35ea12cb8f39af48d8854
|
||||
sentry_flutter: 27892878729f42701297c628eb90e7c6529f3684
|
||||
share_plus: 510bf0af1a42cd602274b4629920c9649c52f4cc
|
||||
share_plus: 11c7b7fa7020465584eca3ff6392c5bc1e399d6e
|
||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
||||
sodium_libs: b9459e5bfc1185349f43472e79fc5d8e526b2bda
|
||||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||
sqlite3: 1d85290c3321153511f6e900ede7a1608718bbd5
|
||||
sqlite3_flutter_libs: e7fc8c9ea2200ff3271f08f127842131746b70e2
|
||||
sqflite: c35dad70033b8862124f8337cc994a809fcd9fa3
|
||||
sqlite3: 0bb0e6389d824e40296f531b858a2a0b71c0d2fb
|
||||
sqlite3_flutter_libs: 03311aede9d32fb2d24e32bebb8cd01c3b2e6239
|
||||
tray_manager: a104b5c81b578d83f3c3d0f40a997c8b10810166
|
||||
url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673
|
||||
window_manager: b729e31d38fb04905235df9ea896128991cad99e
|
||||
window_manager: 1d01fa7ac65a6e6f83b965471b1a7fdd3f06166c
|
||||
|
||||
PODFILE CHECKSUM: 6ff827273ace187339fc5d3684072a26ad85c298
|
||||
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
enableGPUValidationMode = "1"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
|
||||
name: ente_auth
|
||||
description: ente two-factor authenticator
|
||||
version: 4.4.3+443
|
||||
version: 4.4.1+441
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
@@ -10,11 +10,11 @@ environment:
|
||||
dependencies:
|
||||
adaptive_theme: ^3.1.0 # done
|
||||
app_links: ^6.3.3
|
||||
archive: ^4.0.7
|
||||
archive: ^3.3.7
|
||||
auto_size_text: ^3.0.0
|
||||
base32: ^2.1.3
|
||||
bip39: ^1.0.6 #done
|
||||
bloc: ^9.0.0
|
||||
bloc: ^8.1.2
|
||||
clipboard: ^0.1.3
|
||||
collection: ^1.18.0 # dart
|
||||
confetti: ^0.8.0
|
||||
@@ -22,7 +22,7 @@ dependencies:
|
||||
convert: ^3.1.1
|
||||
device_info_plus: ^9.1.1
|
||||
dio: ^5.8.0+1
|
||||
dotted_border: ^3.1.0
|
||||
dotted_border: ^2.0.0+2
|
||||
dropdown_button2: ^2.3.9
|
||||
email_validator: ^3.0.0
|
||||
ente_crypto_dart:
|
||||
@@ -32,19 +32,19 @@ dependencies:
|
||||
expandable: ^5.0.1
|
||||
expansion_tile_card: ^3.0.0
|
||||
ffi: ^2.1.0
|
||||
figma_squircle: ^0.6.3
|
||||
file_picker: ^10.2.0
|
||||
figma_squircle: ^0.5.3
|
||||
file_picker: ^8.1.7
|
||||
# https://github.com/incrediblezayed/file_saver/issues/86
|
||||
file_saver: ^0.3.0
|
||||
file_saver: ^0.2.11
|
||||
fixnum: ^1.1.0
|
||||
fk_user_agent: ^2.1.0
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_animate: ^4.1.0
|
||||
flutter_bloc: ^9.1.1
|
||||
flutter_bloc: ^8.0.1
|
||||
flutter_context_menu: ^0.2.0
|
||||
flutter_displaymode: ^0.6.0
|
||||
flutter_email_sender: ^7.0.0
|
||||
flutter_email_sender: ^6.0.2
|
||||
# revert to pub.dev when merged
|
||||
# https://github.com/pichillilorenzo/flutter_inappwebview/pull/2548
|
||||
flutter_inappwebview:
|
||||
@@ -57,7 +57,7 @@ dependencies:
|
||||
git:
|
||||
url: https://github.com/eaceto/flutter_local_authentication
|
||||
ref: 1ac346a04592a05fd75acccf2e01fa3c7e955d96
|
||||
flutter_local_notifications: ^18.0.1
|
||||
flutter_local_notifications: ^17.2.2
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
flutter_native_splash: ^2.2.13
|
||||
@@ -87,27 +87,30 @@ dependencies:
|
||||
pinput: ^5.0.0
|
||||
pointycastle: ^3.7.3
|
||||
privacy_screen: ^0.0.6
|
||||
protobuf: ^4.1.0
|
||||
protobuf: ^3.0.0
|
||||
qr_code_scanner: ^1.0.1
|
||||
qr_flutter: ^4.1.0
|
||||
sentry: ^8.14.2
|
||||
sentry_flutter: ^8.14.2
|
||||
share_plus: ^11.0.0
|
||||
share_plus: ^10.0.2
|
||||
shared_preferences: ^2.0.5
|
||||
sqflite: ^2.4.2
|
||||
sqflite:
|
||||
git:
|
||||
url: https://github.com/tekartik/sqflite
|
||||
path: sqflite
|
||||
sqflite_common_ffi: ^2.3.0+4
|
||||
sqlite3: ^2.4.3
|
||||
sqlite3_flutter_libs: ^0.5.24
|
||||
steam_totp: ^0.0.1
|
||||
step_progress_indicator: ^1.0.2
|
||||
styled_text: ^8.1.0
|
||||
tray_manager: ^0.5.0
|
||||
tray_manager: ^0.2.1
|
||||
tuple: ^2.0.0
|
||||
url_launcher: ^6.3.1
|
||||
url_launcher_ios: ^6.3.1
|
||||
uuid: ^4.2.2
|
||||
win32: ^5.1.1
|
||||
window_manager: ^0.5.0
|
||||
window_manager: ^0.4.2
|
||||
xdg_directories: ^1.0.4
|
||||
|
||||
dev_dependencies:
|
||||
@@ -115,7 +118,7 @@ dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
json_serializable: ^6.2.0
|
||||
lints: ^5.1.1
|
||||
lints: ^5.0.0
|
||||
mocktail: ^1.0.3
|
||||
|
||||
# The following section is specific to Flutter.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import "package:ente_auth/l10n/arb/app_localizations.dart";
|
||||
import "package:ente_auth/l10n/l10n.dart";
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_localizations/flutter_localizations.dart";
|
||||
import "package:flutter_test/flutter_test.dart";
|
||||
@@ -8,6 +8,7 @@ extension PumpApp on WidgetTester {
|
||||
return pumpWidget(
|
||||
MaterialApp(
|
||||
localizationsDelegates: const [
|
||||
AppLocalizations.delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
],
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <flutter_local_authentication/flutter_local_authentication_plugin_c_api.h>
|
||||
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
|
||||
#include <local_auth_windows/local_auth_plugin.h>
|
||||
#include <screen_retriever_windows/screen_retriever_windows_plugin_c_api.h>
|
||||
#include <screen_retriever/screen_retriever_plugin.h>
|
||||
#include <sentry_flutter/sentry_flutter_plugin.h>
|
||||
#include <share_plus/share_plus_windows_plugin_c_api.h>
|
||||
#include <sodium_libs/sodium_libs_plugin_c_api.h>
|
||||
@@ -37,8 +37,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
|
||||
LocalAuthPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("LocalAuthPlugin"));
|
||||
ScreenRetrieverWindowsPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("ScreenRetrieverWindowsPluginCApi"));
|
||||
ScreenRetrieverPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("ScreenRetrieverPlugin"));
|
||||
SentryFlutterPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("SentryFlutterPlugin"));
|
||||
SharePlusWindowsPluginCApiRegisterWithRegistrar(
|
||||
|
||||
@@ -10,7 +10,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
||||
flutter_local_authentication
|
||||
flutter_secure_storage_windows
|
||||
local_auth_windows
|
||||
screen_retriever_windows
|
||||
screen_retriever
|
||||
sentry_flutter
|
||||
share_plus
|
||||
sodium_libs
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"flutter": "3.29.3"
|
||||
}
|
||||
3
mobile/apps/photos/.gitignore
vendored
3
mobile/apps/photos/.gitignore
vendored
@@ -43,6 +43,3 @@ fastlane/report.xml
|
||||
|
||||
# Android related
|
||||
android/app/build/
|
||||
|
||||
# FVM Version Cache
|
||||
.fvm/
|
||||
@@ -46,25 +46,27 @@ You can alternatively install the build from PlayStore or F-Droid.
|
||||
|
||||
## 🧑💻 Building from source
|
||||
|
||||
1. [Install Flutter v3.29.3](https://flutter.dev/docs/get-started/install).
|
||||
1. Install [Flutter v3.24.3](https://flutter.dev/docs/get-started/install) and [Rust v1.85.1](https://www.rust-lang.org/tools/install).
|
||||
|
||||
2. Pull in all submodules with `git submodule update --init --recursive`
|
||||
2. Install [Flutter Rust Bridge](https://cjycode.com/flutter_rust_bridge/) with `cargo install flutter_rust_bridge_codegen`
|
||||
|
||||
3. Enable repo git hooks `git config core.hooksPath hooks`
|
||||
3. Pull in all submodules with `git submodule update --init --recursive`
|
||||
|
||||
4. If using Visual Studio Code, add the [Flutter
|
||||
4. Enable repo git hooks `git config core.hooksPath hooks`
|
||||
|
||||
5. If using Visual Studio Code, add the [Flutter
|
||||
Intl](https://marketplace.visualstudio.com/items?itemName=localizely.flutter-intl)
|
||||
extension
|
||||
|
||||
5. On Android:
|
||||
6. On Android:
|
||||
|
||||
* For development, run `flutter run -t lib/main.dart --flavor independent`
|
||||
- For development, run `flutter run -t lib/main.dart --flavor independent`
|
||||
|
||||
* For building APK, [setup your
|
||||
- For building APK, [setup your
|
||||
keystore](https://docs.flutter.dev/deployment/android#create-an-upload-keystore)
|
||||
and run `flutter build apk --release --flavor independent`
|
||||
|
||||
6. For iOS, run `flutter build ios`
|
||||
7. For iOS, run `flutter build ios`
|
||||
|
||||
Some common issues and troubleshooting tips are in [docs/dev](docs/dev.md).
|
||||
|
||||
@@ -88,11 +90,12 @@ issue](https://github.com/ente-io/ente/issues/new?title=Request+for+New+Language
|
||||
to have it added.
|
||||
|
||||
## Certificate Fingerprints
|
||||
|
||||
|
||||
- **SHA1**: E1:60:10:18:B6:B0:2E:A3:74:6F:90:67:50:30:29:75:0E:EF:6D:39
|
||||
- **SHA256**: 35:ED:56:81:B7:0B:B3:BD:35:D9:0D:85:6A:F5:69:4C:50:4D:EF:46:AA:D8:3F:77:7B:1C:67:5C:F4:51:35:0B
|
||||
|
||||
To verify these fingerprints, use the following command:
|
||||
|
||||
```bash
|
||||
apksigner verify --print-certs <path_to_apk>
|
||||
```
|
||||
|
||||
@@ -31,10 +31,9 @@ if (keystorePropertiesFile.exists()) {
|
||||
android {
|
||||
namespace = "io.ente.photos"
|
||||
compileSdk = 35
|
||||
ndkVersion = flutter.ndkVersion
|
||||
ndkVersion = "28.0.13004108"
|
||||
|
||||
compileOptions {
|
||||
coreLibraryDesugaringEnabled = true
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
@@ -133,7 +132,7 @@ flutter {
|
||||
source = "../.."
|
||||
}
|
||||
|
||||
dependencies {
|
||||
dependencies {
|
||||
implementation 'io.sentry:sentry-android:2.0.0'
|
||||
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.21'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.0'
|
||||
@@ -143,7 +142,7 @@ dependencies {
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test:runner:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
||||
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
|
||||
|
||||
|
||||
constraints {
|
||||
implementation("androidx.work:work-runtime:2.8.1") {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
package io.ente.photos
|
||||
|
||||
import io.flutter.embedding.android.FlutterFragmentActivity
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
import io.flutter.plugins.GeneratedPluginRegistrant
|
||||
|
||||
class MainActivity : FlutterFragmentActivity() {}
|
||||
class MainActivity : FlutterFragmentActivity() {
|
||||
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
||||
GeneratedPluginRegistrant.registerWith(flutterEngine)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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-8.3-all.zip
|
||||
|
||||
@@ -18,7 +18,7 @@ pluginManagement {
|
||||
|
||||
plugins {
|
||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||
id "com.android.application" version "8.6.0" apply false
|
||||
id "com.android.application" version "8.1.0" apply false
|
||||
id "org.jetbrains.kotlin.android" version "2.1.10" apply false
|
||||
}
|
||||
|
||||
|
||||
8
mobile/apps/photos/flutter_rust_bridge.yaml
Normal file
8
mobile/apps/photos/flutter_rust_bridge.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
rust_input: crate::api
|
||||
rust_root: rust/
|
||||
dart_output: lib/src/rust
|
||||
|
||||
dart_preamble: |
|
||||
// ignore_for_file: require_trailing_commas
|
||||
|
||||
web: false
|
||||
@@ -91,10 +91,9 @@ Future<void> dismissUpdateAppDialog(WidgetTester tester) async {
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
|
||||
///Use this widget as floating action buttom in HomeWidget so that frames
|
||||
///are built and rendered continuously so that timeline trace has continuous
|
||||
///data. Change the duraiton in `_startTimer()` to control the duraiton of
|
||||
///are built and rendered continuously so that timeline trace has continuous
|
||||
///data. Change the duraiton in `_startTimer()` to control the duraiton of
|
||||
///test on app init.
|
||||
|
||||
// class TempWidget extends StatefulWidget {
|
||||
@@ -127,4 +126,4 @@ Future<void> dismissUpdateAppDialog(WidgetTester tester) async {
|
||||
// ? const CircularProgressIndicator()
|
||||
// : const SizedBox.shrink();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
13
mobile/apps/photos/integration_test/simple_test.dart
Normal file
13
mobile/apps/photos/integration_test/simple_test.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import "package:photos/src/rust/api/simple.dart";
|
||||
import 'package:photos/src/rust/frb_generated.dart';
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
setUpAll(() async => await RustLib.init());
|
||||
testWidgets('Can call rust function', (WidgetTester tester) async {
|
||||
final testString = greet(name: "Tom");
|
||||
expect(testString.contains('Tom'), true);
|
||||
});
|
||||
}
|
||||
2
mobile/apps/photos/ios/.gitignore
vendored
2
mobile/apps/photos/ios/.gitignore
vendored
@@ -32,5 +32,3 @@ Flutter/.last_build_id
|
||||
!default.mode2v3
|
||||
!default.pbxuser
|
||||
!default.perspectivev3
|
||||
|
||||
Flutter/ephemeral
|
||||
@@ -1,6 +1,7 @@
|
||||
source 'https://github.com/ente-io/ffmpeg-kit-custom-repo-ios.git'
|
||||
# Uncomment this line to define a global platform for your project
|
||||
platform :ios, '13.0'
|
||||
|
||||
source 'https://github.com/ente-io/ffmpeg-kit-custom-repo-ios.git'
|
||||
source 'https://cdn.cocoapods.org/'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
|
||||
@@ -18,37 +18,37 @@ PODS:
|
||||
- Flutter
|
||||
- file_saver (0.0.1):
|
||||
- Flutter
|
||||
- Firebase/CoreOnly (11.15.0):
|
||||
- FirebaseCore (~> 11.15.0)
|
||||
- Firebase/Messaging (11.15.0):
|
||||
- Firebase/CoreOnly (11.8.0):
|
||||
- FirebaseCore (~> 11.8.0)
|
||||
- Firebase/Messaging (11.8.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseMessaging (~> 11.15.0)
|
||||
- firebase_core (3.15.1):
|
||||
- Firebase/CoreOnly (= 11.15.0)
|
||||
- FirebaseMessaging (~> 11.8.0)
|
||||
- firebase_core (3.12.0):
|
||||
- Firebase/CoreOnly (= 11.8.0)
|
||||
- Flutter
|
||||
- firebase_messaging (15.2.9):
|
||||
- Firebase/Messaging (= 11.15.0)
|
||||
- firebase_messaging (15.2.3):
|
||||
- Firebase/Messaging (= 11.8.0)
|
||||
- firebase_core
|
||||
- Flutter
|
||||
- FirebaseCore (11.15.0):
|
||||
- FirebaseCoreInternal (~> 11.15.0)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/Logger (~> 8.1)
|
||||
- FirebaseCoreInternal (11.15.0):
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- FirebaseInstallations (11.15.0):
|
||||
- FirebaseCore (~> 11.15.0)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||
- FirebaseCore (11.8.1):
|
||||
- FirebaseCoreInternal (~> 11.8.0)
|
||||
- GoogleUtilities/Environment (~> 8.0)
|
||||
- GoogleUtilities/Logger (~> 8.0)
|
||||
- FirebaseCoreInternal (11.8.0):
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.0)"
|
||||
- FirebaseInstallations (11.8.0):
|
||||
- FirebaseCore (~> 11.8.0)
|
||||
- GoogleUtilities/Environment (~> 8.0)
|
||||
- GoogleUtilities/UserDefaults (~> 8.0)
|
||||
- PromisesObjC (~> 2.4)
|
||||
- FirebaseMessaging (11.15.0):
|
||||
- FirebaseCore (~> 11.15.0)
|
||||
- FirebaseMessaging (11.8.0):
|
||||
- FirebaseCore (~> 11.8.0)
|
||||
- FirebaseInstallations (~> 11.0)
|
||||
- GoogleDataTransport (~> 10.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/Reachability (~> 8.1)
|
||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
|
||||
- GoogleUtilities/Environment (~> 8.0)
|
||||
- GoogleUtilities/Reachability (~> 8.0)
|
||||
- GoogleUtilities/UserDefaults (~> 8.0)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- Flutter (1.0.0)
|
||||
- flutter_email_sender (0.0.1):
|
||||
@@ -127,6 +127,9 @@ PODS:
|
||||
- libwebp/sharpyuv (1.5.0)
|
||||
- libwebp/webp (1.5.0):
|
||||
- libwebp/sharpyuv
|
||||
- local_auth_darwin (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- local_auth_ios (0.0.1):
|
||||
- Flutter
|
||||
- Mantle (2.2.0):
|
||||
@@ -173,7 +176,7 @@ PODS:
|
||||
- FlutterMacOS
|
||||
- permission_handler_apple (9.3.0):
|
||||
- Flutter
|
||||
- photo_manager (3.7.1):
|
||||
- photo_manager (2.0.0):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- privacy_screen (0.0.1):
|
||||
@@ -200,26 +203,23 @@ PODS:
|
||||
- sqflite_darwin (0.0.4):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- sqlite3 (3.50.1):
|
||||
- sqlite3/common (= 3.50.1)
|
||||
- sqlite3/common (3.50.1)
|
||||
- sqlite3/dbstatvtab (3.50.1):
|
||||
- sqlite3 (3.49.2):
|
||||
- sqlite3/common (= 3.49.2)
|
||||
- sqlite3/common (3.49.2)
|
||||
- sqlite3/dbstatvtab (3.49.2):
|
||||
- sqlite3/common
|
||||
- sqlite3/fts5 (3.50.1):
|
||||
- sqlite3/fts5 (3.49.2):
|
||||
- sqlite3/common
|
||||
- sqlite3/math (3.50.1):
|
||||
- sqlite3/perf-threadsafe (3.49.2):
|
||||
- sqlite3/common
|
||||
- sqlite3/perf-threadsafe (3.50.1):
|
||||
- sqlite3/common
|
||||
- sqlite3/rtree (3.50.1):
|
||||
- sqlite3/rtree (3.49.2):
|
||||
- sqlite3/common
|
||||
- sqlite3_flutter_libs (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- sqlite3 (~> 3.50.1)
|
||||
- sqlite3 (~> 3.49.0)
|
||||
- sqlite3/dbstatvtab
|
||||
- sqlite3/fts5
|
||||
- sqlite3/math
|
||||
- sqlite3/perf-threadsafe
|
||||
- sqlite3/rtree
|
||||
- system_info_plus (0.0.1):
|
||||
@@ -269,6 +269,7 @@ DEPENDENCIES:
|
||||
- in_app_purchase_storekit (from `.symlinks/plugins/in_app_purchase_storekit/darwin`)
|
||||
- integration_test (from `.symlinks/plugins/integration_test/ios`)
|
||||
- launcher_icon_switcher (from `.symlinks/plugins/launcher_icon_switcher/ios`)
|
||||
- local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`)
|
||||
- local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`)
|
||||
- maps_launcher (from `.symlinks/plugins/maps_launcher/ios`)
|
||||
- media_extension (from `.symlinks/plugins/media_extension/ios`)
|
||||
@@ -287,6 +288,7 @@ DEPENDENCIES:
|
||||
- photo_manager (from `.symlinks/plugins/photo_manager/ios`)
|
||||
- privacy_screen (from `.symlinks/plugins/privacy_screen/ios`)
|
||||
- receive_sharing_intent (from `.symlinks/plugins/receive_sharing_intent/ios`)
|
||||
- rust_lib_photos (from `.symlinks/plugins/rust_lib_photos/ios`)
|
||||
- sentry_flutter (from `.symlinks/plugins/sentry_flutter/ios`)
|
||||
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
@@ -303,7 +305,7 @@ DEPENDENCIES:
|
||||
- workmanager (from `.symlinks/plugins/workmanager/ios`)
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/ente-io/ffmpeg-kit-custom-repo-ios:
|
||||
https://github.com/ente-io/ffmpeg-kit-custom-repo-ios.git:
|
||||
- ffmpeg_kit_custom
|
||||
trunk:
|
||||
- Firebase
|
||||
@@ -376,6 +378,8 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/integration_test/ios"
|
||||
launcher_icon_switcher:
|
||||
:path: ".symlinks/plugins/launcher_icon_switcher/ios"
|
||||
local_auth_darwin:
|
||||
:path: ".symlinks/plugins/local_auth_darwin/darwin"
|
||||
local_auth_ios:
|
||||
:path: ".symlinks/plugins/local_auth_ios/ios"
|
||||
maps_launcher:
|
||||
@@ -412,6 +416,8 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/privacy_screen/ios"
|
||||
receive_sharing_intent:
|
||||
:path: ".symlinks/plugins/receive_sharing_intent/ios"
|
||||
rust_lib_photos:
|
||||
:path: ".symlinks/plugins/rust_lib_photos/ios"
|
||||
sentry_flutter:
|
||||
:path: ".symlinks/plugins/sentry_flutter/ios"
|
||||
share_plus:
|
||||
@@ -442,83 +448,84 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/workmanager/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
app_links: 76b66b60cc809390ca1ad69bfd66b998d2387ac7
|
||||
battery_info: 83f3aae7be2fccefab1d2bf06b8aa96f11c8bcdd
|
||||
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
||||
cupertino_http: 94ac07f5ff090b8effa6c5e2c47871d48ab7c86c
|
||||
dart_ui_isolate: 46f6714abe6891313267153ef6f9748d8ecfcab1
|
||||
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
|
||||
app_links: f3e17e4ee5e357b39d8b95290a9b2c299fca71c6
|
||||
battery_info: b6c551049266af31556b93c9d9b9452cfec0219f
|
||||
connectivity_plus: 2a701ffec2c0ae28a48cf7540e279787e77c447d
|
||||
cupertino_http: 947a233f40cfea55167a49f2facc18434ea117ba
|
||||
dart_ui_isolate: d5bcda83ca4b04f129d70eb90110b7a567aece14
|
||||
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
|
||||
ffmpeg_kit_custom: 682b4f2f1ff1f8abae5a92f6c3540f2441d5be99
|
||||
ffmpeg_kit_flutter: 915b345acc97d4142e8a9a8549d177ff10f043f5
|
||||
file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6
|
||||
Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e
|
||||
firebase_core: ece862f94b2bc72ee0edbeec7ab5c7cb09fe1ab5
|
||||
firebase_messaging: e1a5fae495603115be1d0183bc849da748734e2b
|
||||
FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e
|
||||
FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4
|
||||
FirebaseInstallations: 317270fec08a5d418fdbc8429282238cab3ac843
|
||||
FirebaseMessaging: 3b26e2cee503815e01c3701236b020aa9b576f09
|
||||
ffmpeg_kit_flutter: 9dce4803991478c78c6fb9f972703301101095fe
|
||||
file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808
|
||||
Firebase: d80354ed7f6df5f9aca55e9eb47cc4b634735eaf
|
||||
firebase_core: 6e223dfa350b2edceb729cea505eaaef59330682
|
||||
firebase_messaging: 07fde77ae28c08616a1d4d870450efc2b38cf40d
|
||||
FirebaseCore: 99fe0c4b44a39f37d99e6404e02009d2db5d718d
|
||||
FirebaseCoreInternal: df24ce5af28864660ecbd13596fc8dd3a8c34629
|
||||
FirebaseInstallations: 6c963bd2a86aca0481eef4f48f5a4df783ae5917
|
||||
FirebaseMessaging: 487b634ccdf6f7b7ff180fdcb2a9935490f764e8
|
||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||
flutter_email_sender: aa1e9772696691d02cd91fea829856c11efb8e58
|
||||
flutter_image_compress_common: 1697a328fd72bfb335507c6bca1a65fa5ad87df1
|
||||
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
||||
flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb
|
||||
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
||||
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
||||
flutter_sodium: 7e4621538491834eba53bd524547854bcbbd6987
|
||||
flutter_timezone: 7c838e17ffd4645d261e87037e5bebf6d38fe544
|
||||
fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1
|
||||
flutter_email_sender: e03bdda7637bcd3539bfe718fddd980e9508efaa
|
||||
flutter_image_compress_common: ec1d45c362c9d30a3f6a0426c297f47c52007e3e
|
||||
flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4
|
||||
flutter_local_notifications: ff50f8405aaa0ccdc7dcfb9022ca192e8ad9688f
|
||||
flutter_native_splash: f71420956eb811e6d310720fee915f1d42852e7a
|
||||
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
|
||||
flutter_sodium: a00383520fc689c688b66fd3092984174712493e
|
||||
flutter_timezone: ac3da59ac941ff1c98a2e1f0293420e020120282
|
||||
fluttertoast: 21eecd6935e7064cc1fcb733a4c5a428f3f24f0f
|
||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||
home_widget: f169fc41fd807b4d46ab6615dc44d62adbf9f64f
|
||||
image_editor_common: 3de87e7c4804f4ae24c8f8a998362b98c105cac1
|
||||
in_app_purchase_storekit: d1a48cb0f8b29dbf5f85f782f5dd79b21b90a5e6
|
||||
integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e
|
||||
launcher_icon_switcher: 84c218d233505aa7d8655d8fa61a3ba802c022da
|
||||
home_widget: 0434835a4c9a75704264feff6be17ea40e0f0d57
|
||||
image_editor_common: d6f6644ae4a6de80481e89fe6d0a8c49e30b4b43
|
||||
in_app_purchase_storekit: a1ce04056e23eecc666b086040239da7619cd783
|
||||
integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573
|
||||
launcher_icon_switcher: 8e0ad2131a20c51c1dd939896ee32e70cd845b37
|
||||
libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
|
||||
local_auth_ios: f7a1841beef3151d140a967c2e46f30637cdf451
|
||||
local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3
|
||||
local_auth_ios: 5046a18c018dd973247a0564496c8898dbb5adf9
|
||||
Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d
|
||||
maps_launcher: edf829809ba9e894d70e569bab11c16352dedb45
|
||||
media_extension: 671e2567880d96c95c65c9a82ccceed8f2e309fd
|
||||
media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854
|
||||
media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474
|
||||
motion_sensors: 741e702c17467b9569a92165dda8d4d88c6167f1
|
||||
motionphoto: 23e2aeb5c6380112f69468d71f970fa7438e5ed1
|
||||
move_to_background: 7e3467dd2a1d1013e98c9c1cb93fd53cd7ef9d84
|
||||
maps_launcher: 2e5b6a2d664ec6c27f82ffa81b74228d770ab203
|
||||
media_extension: 6618f07abd762cdbfaadf1b0c56a287e820f0c84
|
||||
media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1
|
||||
media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e
|
||||
motion_sensors: 03f55b7c637a7e365a0b5f9697a449f9059d5d91
|
||||
motionphoto: 8b65ce50c7d7ff3c767534fc3768b2eed9ac24e4
|
||||
move_to_background: cd3091014529ec7829e342ad2d75c0a11f4378a5
|
||||
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||
native_video_player: 6809dec117e8997161dbfb42a6f90d6df71a504d
|
||||
objective_c: 89e720c30d716b036faf9c9684022048eee1eee2
|
||||
onnxruntime: f9b296392c96c42882be020a59dbeac6310d81b2
|
||||
native_video_player: 29ab24a926804ac8c4a57eb6d744c7d927c2bc3e
|
||||
objective_c: 77e887b5ba1827970907e10e832eec1683f3431d
|
||||
onnxruntime: e7c2ae44385191eaad5ae64c935a72debaddc997
|
||||
onnxruntime-c: a909204639a1f035f575127ac406f781ac797c9c
|
||||
onnxruntime-objc: b6fab0f1787aa6f7190c2013f03037df4718bd8b
|
||||
open_mail_app: 7314a609e88eed22d53671279e189af7a0ab0f11
|
||||
open_mail_app: 70273c53f768beefdafbe310c3d9086e4da3cb02
|
||||
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
|
||||
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
|
||||
photo_manager: 1d80ae07a89a67dfbcae95953a1e5a24af7c3e62
|
||||
privacy_screen: 3159a541f5d3a31bea916cfd4e58f9dc722b3fd4
|
||||
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
|
||||
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
|
||||
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
|
||||
photo_manager: ff695c7a1dd5bc379974953a2b5c0a293f7c4c8a
|
||||
privacy_screen: 1a131c052ceb3c3659934b003b0d397c2381a24e
|
||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||
receive_sharing_intent: 222384f00ffe7e952bbfabaa9e3967cb87e5fe00
|
||||
receive_sharing_intent: 79c848f5b045674ad60b9fea3bafea59962ad2c1
|
||||
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
||||
SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
|
||||
Sentry: da60d980b197a46db0b35ea12cb8f39af48d8854
|
||||
sentry_flutter: 27892878729f42701297c628eb90e7c6529f3684
|
||||
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
|
||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
||||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||
sqlite3: 1d85290c3321153511f6e900ede7a1608718bbd5
|
||||
sqlite3_flutter_libs: e7fc8c9ea2200ff3271f08f127842131746b70e2
|
||||
system_info_plus: 555ce7047fbbf29154726db942ae785c29211740
|
||||
thermal: d4c48be750d1ddbab36b0e2dcb2471531bc8df41
|
||||
ua_client_hints: 92fe0d139619b73ec9fcb46cc7e079a26178f586
|
||||
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
||||
video_player_avfoundation: 2cef49524dd1f16c5300b9cd6efd9611ce03639b
|
||||
video_thumbnail: b637e0ad5f588ca9945f6e2c927f73a69a661140
|
||||
volume_controller: 3657a1f65bedb98fa41ff7dc5793537919f31b12
|
||||
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
|
||||
workmanager: b89e4e4445d8b57ee2fdbf1c3925696ebe5b8990
|
||||
sentry_flutter: 2df8b0aab7e4aba81261c230cbea31c82a62dd1b
|
||||
share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
|
||||
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
|
||||
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
|
||||
sqlite3: 3c950dc86011117c307eb0b28c4a7bb449dce9f1
|
||||
sqlite3_flutter_libs: 069c435986dd4b63461aecd68f4b30be4a9e9daa
|
||||
system_info_plus: 5393c8da281d899950d751713575fbf91c7709aa
|
||||
thermal: a9261044101ae8f532fa29cab4e8270b51b3f55c
|
||||
ua_client_hints: aeabd123262c087f0ce151ef96fa3ab77bfc8b38
|
||||
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
|
||||
video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3
|
||||
video_thumbnail: 94ba6705afbaa120b77287080424930f23ea0c40
|
||||
volume_controller: 2e3de73d6e7e81a0067310d17fb70f2f86d71ac7
|
||||
wakelock_plus: 373cfe59b235a6dd5837d0fb88791d2f13a90d56
|
||||
workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6
|
||||
|
||||
PODFILE CHECKSUM: cce2cd3351d3488dca65b151118552b680e23635
|
||||
PODFILE CHECKSUM: a8ef88ad74ba499756207e7592c6071a96756d18
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
|
||||
@@ -548,6 +548,7 @@
|
||||
"${BUILT_PRODUCTS_DIR}/integration_test/integration_test.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/launcher_icon_switcher/launcher_icon_switcher.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/libwebp/libwebp.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/local_auth_darwin/local_auth_darwin.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/local_auth_ios/local_auth_ios.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/maps_launcher/maps_launcher.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/media_extension/media_extension.framework",
|
||||
@@ -565,6 +566,7 @@
|
||||
"${BUILT_PRODUCTS_DIR}/photo_manager/photo_manager.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/privacy_screen/privacy_screen.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/receive_sharing_intent/receive_sharing_intent.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/rust_lib_photos/rust_lib_photos.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/sentry_flutter/sentry_flutter.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/share_plus/share_plus.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/shared_preferences_foundation/shared_preferences_foundation.framework",
|
||||
@@ -643,6 +645,7 @@
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/integration_test.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/launcher_icon_switcher.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libwebp.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/local_auth_darwin.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/local_auth_ios.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/maps_launcher.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/media_extension.framework",
|
||||
@@ -660,6 +663,7 @@
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/photo_manager.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/privacy_screen.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/receive_sharing_intent.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/rust_lib_photos.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sentry_flutter.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/share_plus.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences_foundation.framework",
|
||||
|
||||
@@ -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">
|
||||
|
||||
3
mobile/apps/photos/l10n.yaml
Normal file
3
mobile/apps/photos/l10n.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
arb-dir: lib/l10n
|
||||
template-arb-file: intl_en.arb
|
||||
output-localization-file: app_localizations.dart
|
||||
@@ -5,7 +5,7 @@ import 'package:adaptive_theme/adaptive_theme.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import "package:flutter_localizations/flutter_localizations.dart";
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:home_widget/home_widget.dart' as hw;
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:media_extension/media_extension_action_types.dart';
|
||||
@@ -20,7 +20,6 @@ import 'package:photos/services/app_lifecycle_service.dart';
|
||||
import "package:photos/services/home_widget_service.dart";
|
||||
import "package:photos/services/memory_home_widget_service.dart";
|
||||
import "package:photos/services/people_home_widget_service.dart";
|
||||
import "package:photos/services/smart_albums_service.dart";
|
||||
import 'package:photos/services/sync/sync_service.dart';
|
||||
import 'package:photos/ui/tabs/home_widget.dart';
|
||||
import "package:photos/ui/viewer/actions/file_viewer.dart";
|
||||
@@ -75,10 +74,8 @@ class _EnteAppState extends State<EnteApp> with WidgetsBindingObserver {
|
||||
_peopleChangedSubscription = Bus.instance.on<PeopleChangedEvent>().listen(
|
||||
(event) async {
|
||||
_changeCallbackDebouncer.run(
|
||||
() async {
|
||||
unawaited(PeopleHomeWidgetService.instance.checkPeopleChanged());
|
||||
unawaited(SmartAlbumsService.instance.syncSmartAlbums());
|
||||
},
|
||||
() async =>
|
||||
unawaited(PeopleHomeWidgetService.instance.checkPeopleChanged()),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -146,10 +143,8 @@ class _EnteAppState extends State<EnteApp> with WidgetsBindingObserver {
|
||||
supportedLocales: appSupportedLocales,
|
||||
localeListResolutionCallback: localResolutionCallBack,
|
||||
localizationsDelegates: const [
|
||||
...AppLocalizations.localizationsDelegates,
|
||||
S.delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -171,10 +166,8 @@ class _EnteAppState extends State<EnteApp> with WidgetsBindingObserver {
|
||||
supportedLocales: appSupportedLocales,
|
||||
localeListResolutionCallback: localResolutionCallBack,
|
||||
localizationsDelegates: const [
|
||||
...AppLocalizations.localizationsDelegates,
|
||||
S.delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
import "dart:io";
|
||||
|
||||
import 'package:photos/core/cache/lru_map.dart';
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
library super_logging;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
import 'dart:core';
|
||||
|
||||
@@ -58,7 +58,7 @@ bool isHandledSyncError(Object errObj) {
|
||||
|
||||
class LockAlreadyAcquiredError extends Error {}
|
||||
|
||||
class LockFreedError extends Error{}
|
||||
class LockFreedError extends Error {}
|
||||
|
||||
class UnauthorizedError extends Error {}
|
||||
|
||||
|
||||
@@ -128,21 +128,4 @@ extension EntitiesDB on FilesDB {
|
||||
}
|
||||
return maps.values.first as String?;
|
||||
}
|
||||
|
||||
Future<Map<String, int>> getUpdatedAts(
|
||||
EntityType type,
|
||||
List<String> ids,
|
||||
) async {
|
||||
final db = await sqliteAsyncDB;
|
||||
final List<Map<String, dynamic>> maps = await db.getAll(
|
||||
'SELECT id, updatedAt FROM entities WHERE type = ? AND id IN (${List.filled(ids.length, '?').join(',')})',
|
||||
[type.name, ...ids],
|
||||
);
|
||||
return Map<String, int>.fromEntries(
|
||||
List.generate(
|
||||
maps.length,
|
||||
(i) => MapEntry(maps[i]['id'] as String, maps[i]['updatedAt'] as int),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1479,7 +1479,6 @@ class FilesDB with SqlDbBase {
|
||||
|
||||
final inParam = ids.map((id) => "'$id'").join(',');
|
||||
final db = await instance.sqliteAsyncDB;
|
||||
|
||||
final results = await db.getAll(
|
||||
'SELECT * FROM $filesTable WHERE $columnUploadedFileID IN ($inParam) ORDER BY $columnCreationTime $order',
|
||||
);
|
||||
|
||||
238
mobile/apps/photos/lib/db/ml/clip_vector_db.dart
Normal file
238
mobile/apps/photos/lib/db/ml/clip_vector_db.dart
Normal file
@@ -0,0 +1,238 @@
|
||||
import "dart:typed_data" show Float32List;
|
||||
|
||||
import "package:flutter_rust_bridge/flutter_rust_bridge.dart" show Uint64List;
|
||||
import "package:logging/logging.dart";
|
||||
import "package:path/path.dart";
|
||||
import "package:path_provider/path_provider.dart";
|
||||
import "package:photos/models/ml/vector.dart";
|
||||
import "package:photos/services/machine_learning/semantic_search/query_result.dart";
|
||||
import "package:photos/src/rust/api/usearch_api.dart";
|
||||
|
||||
class ClipVectorDB {
|
||||
static final Logger _logger = Logger("ClipVectorDB");
|
||||
|
||||
static const _databaseName = "ente.ml.vectordb.clip";
|
||||
|
||||
static final BigInt _embeddingDimension = BigInt.from(512);
|
||||
|
||||
static Logger get logger => _logger;
|
||||
|
||||
// Singleton pattern
|
||||
ClipVectorDB._privateConstructor();
|
||||
static final instance = ClipVectorDB._privateConstructor();
|
||||
factory ClipVectorDB() => instance;
|
||||
|
||||
// only have a single app-wide reference to the database
|
||||
static Future<VectorDb>? _vectorDbFuture;
|
||||
|
||||
Future<VectorDb> get _vectorDB async {
|
||||
_vectorDbFuture ??= _initVectorDB();
|
||||
return _vectorDbFuture!;
|
||||
}
|
||||
|
||||
Future<VectorDb> _initVectorDB() async {
|
||||
final documentsDirectory = await getApplicationDocumentsDirectory();
|
||||
final String databaseDirectory =
|
||||
join(documentsDirectory.path, _databaseName);
|
||||
_logger.info("Opening vectorDB access: DB path " + databaseDirectory);
|
||||
final vectorDB = VectorDb(
|
||||
filePath: databaseDirectory,
|
||||
dimensions: _embeddingDimension,
|
||||
);
|
||||
final stats = await getIndexStats(vectorDB);
|
||||
_logger.info("VectorDB connection opened with stats: ${stats.toString()}");
|
||||
|
||||
return vectorDB;
|
||||
}
|
||||
|
||||
Future<void> insertEmbedding({
|
||||
required int fileID,
|
||||
required List<double> embedding,
|
||||
}) async {
|
||||
final db = await _vectorDB;
|
||||
try {
|
||||
await db.addVector(key: BigInt.from(fileID), vector: embedding);
|
||||
} catch (e, s) {
|
||||
_logger.severe("Error inserting embedding", e, s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> bulkInsertEmbeddings({
|
||||
required List<int> fileIDs,
|
||||
required List<Float32List> embeddings,
|
||||
}) async {
|
||||
final db = await _vectorDB;
|
||||
final bigKeys = Uint64List.fromList(fileIDs);
|
||||
try {
|
||||
await db.bulkAddVectors(keys: bigKeys, vectors: embeddings);
|
||||
} catch (e, s) {
|
||||
_logger.severe("Error bulk inserting embeddings", e, s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<EmbeddingVector>> getEmbeddings(List<int> fileIDs) async {
|
||||
final db = await _vectorDB;
|
||||
try {
|
||||
final keys = Uint64List.fromList(fileIDs);
|
||||
final vectors = await db.bulkGetVectors(keys: keys);
|
||||
return List.generate(
|
||||
vectors.length,
|
||||
(index) => EmbeddingVector(
|
||||
fileID: fileIDs[index],
|
||||
embedding: vectors[index],
|
||||
),
|
||||
);
|
||||
} catch (e, s) {
|
||||
_logger.severe("Error getting embeddings", e, s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteEmbeddings(List<int> fileIDs) async {
|
||||
final db = await _vectorDB;
|
||||
try {
|
||||
final deletedCount =
|
||||
await db.bulkRemoveVectors(keys: Uint64List.fromList(fileIDs));
|
||||
_logger.info(
|
||||
"Deleted $deletedCount embeddings, from ${fileIDs.length} keys",
|
||||
);
|
||||
} catch (e, s) {
|
||||
_logger.severe("Error bulk deleting specific embeddings", e, s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteAllEmbeddings() async {
|
||||
final db = await _vectorDB;
|
||||
try {
|
||||
await db.resetIndex();
|
||||
} catch (e, s) {
|
||||
_logger.severe("Error deleting all embeddings", e, s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteIndex() async {
|
||||
final db = await _vectorDB;
|
||||
try {
|
||||
await db.deleteIndex();
|
||||
_vectorDbFuture = null;
|
||||
} catch (e, s) {
|
||||
_logger.severe("Error deleting index", e, s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<VectorDbStats> getIndexStats([VectorDb? db]) async {
|
||||
db ??= await _vectorDB;
|
||||
try {
|
||||
final stats = await db.getIndexStats();
|
||||
return VectorDbStats(
|
||||
size: stats.$1.toInt(),
|
||||
capacity: stats.$2.toInt(),
|
||||
dimensions: stats.$3.toInt(),
|
||||
fileSize: stats.$4.toInt(),
|
||||
memoryUsage: stats.$5.toInt(),
|
||||
expansionAdd: stats.$6.toInt(),
|
||||
expansionSearch: stats.$7.toInt(),
|
||||
);
|
||||
} catch (e, s) {
|
||||
_logger.severe("Error getting index stats", e, s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<(Uint64List, Float32List)> searchClosestVectors(
|
||||
List<double> query,
|
||||
int count,
|
||||
) async {
|
||||
final db = await _vectorDB;
|
||||
try {
|
||||
final result =
|
||||
await db.searchVectors(query: query, count: BigInt.from(count));
|
||||
return result;
|
||||
} catch (e, s) {
|
||||
_logger.severe("Error searching closest vectors", e, s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<(BigInt, double)> searchClosestVector(
|
||||
List<double> query,
|
||||
) async {
|
||||
final db = await _vectorDB;
|
||||
try {
|
||||
final result = await db.searchVectors(query: query, count: BigInt.one);
|
||||
return (result.$1[0], result.$2[0]);
|
||||
} catch (e, s) {
|
||||
_logger.severe("Error searching closest vector", e, s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, List<QueryResult>>> computeBulkSimilarities(
|
||||
Map<String, List<double>> textQueryToEmbeddingMap,
|
||||
Map<String, double> minimumSimilarityMap,
|
||||
) async {
|
||||
try {
|
||||
final queryToResults = <String, List<QueryResult>>{};
|
||||
for (final MapEntry<String, List<double>> entry
|
||||
in textQueryToEmbeddingMap.entries) {
|
||||
final query = entry.key;
|
||||
final minimumSimilarity = minimumSimilarityMap[query]!;
|
||||
final textEmbedding = entry.value;
|
||||
final (potentialFileIDs, distances) =
|
||||
await searchClosestVectors(textEmbedding, 1000);
|
||||
final queryResults = <QueryResult>[];
|
||||
for (var i = 0; i < potentialFileIDs.length; i++) {
|
||||
final similarity = 1 - distances[i];
|
||||
if (similarity >= minimumSimilarity) {
|
||||
queryResults
|
||||
.add(QueryResult(potentialFileIDs[i].toInt(), similarity));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
queryToResults[query] = queryResults;
|
||||
}
|
||||
return queryToResults;
|
||||
} catch (e, s) {
|
||||
_logger.severe(
|
||||
"Could not bulk find embeddings similarities using vector DB",
|
||||
e,
|
||||
s,
|
||||
);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VectorDbStats {
|
||||
final int size;
|
||||
final int capacity;
|
||||
final int dimensions;
|
||||
|
||||
// in bytes
|
||||
final int fileSize;
|
||||
final int memoryUsage;
|
||||
|
||||
final int expansionAdd;
|
||||
final int expansionSearch;
|
||||
|
||||
VectorDbStats({
|
||||
required this.size,
|
||||
required this.capacity,
|
||||
required this.dimensions,
|
||||
required this.fileSize,
|
||||
required this.memoryUsage,
|
||||
required this.expansionAdd,
|
||||
required this.expansionSearch,
|
||||
});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "VectorDbStats(size: $size, capacity: $capacity, dimensions: $dimensions, file size on disk (bytes): $fileSize, memory usage (bytes): $memoryUsage, expansionAdd: $expansionAdd, expansionSearch: $expansionSearch)";
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'dart:async';
|
||||
import "dart:io" show File;
|
||||
import "dart:math";
|
||||
|
||||
import "package:collection/collection.dart";
|
||||
@@ -9,6 +10,7 @@ import 'package:path_provider/path_provider.dart';
|
||||
import "package:photos/core/event_bus.dart";
|
||||
import "package:photos/db/common/base.dart";
|
||||
import "package:photos/db/ml/base.dart";
|
||||
import "package:photos/db/ml/clip_vector_db.dart";
|
||||
import "package:photos/db/ml/db_model_mappers.dart";
|
||||
import 'package:photos/db/ml/schema.dart';
|
||||
import "package:photos/events/embedding_updated_event.dart";
|
||||
@@ -18,6 +20,7 @@ import "package:photos/models/ml/face/face.dart";
|
||||
import "package:photos/models/ml/face/face_with_embedding.dart";
|
||||
import "package:photos/models/ml/ml_versions.dart";
|
||||
import "package:photos/models/ml/vector.dart";
|
||||
import "package:photos/service_locator.dart";
|
||||
import "package:photos/services/machine_learning/face_ml/face_clustering/face_db_info_for_clustering.dart";
|
||||
import 'package:photos/services/machine_learning/face_ml/face_filtering/face_filtering_constants.dart';
|
||||
import "package:photos/services/machine_learning/ml_result.dart";
|
||||
@@ -84,6 +87,8 @@ class MLDataDB with SqlDbBase implements IMLDataDB<int> {
|
||||
"MLDataDB Migration took ${stopwatch.elapsedMilliseconds} ms",
|
||||
);
|
||||
stopwatch.stop();
|
||||
_logger.info("Starting CLIP vector DB migration check unawaited");
|
||||
if (flagService.enableVectorDb) unawaited(checkMigrateFillClipVectorDB());
|
||||
|
||||
return asyncDBConnection;
|
||||
}
|
||||
@@ -316,48 +321,28 @@ class MLDataDB with SqlDbBase implements IMLDataDB<int> {
|
||||
// read person from db
|
||||
final db = await instance.asyncDB;
|
||||
if (personID != null) {
|
||||
logger.info("[$recentFileID] Processing personID path: $personID");
|
||||
final List<int> fileId = [recentFileID];
|
||||
logger.info("[$recentFileID] Initial fileId list: $fileId");
|
||||
|
||||
int? avatarFileId;
|
||||
if (avatarFaceId != null) {
|
||||
logger.info(
|
||||
"[$recentFileID] Looking up avatarFileId for avatarFaceId: $avatarFaceId",
|
||||
);
|
||||
avatarFileId = tryGetFileIdFromFaceId(avatarFaceId);
|
||||
logger.info("[$recentFileID] avatarFileId result: $avatarFileId");
|
||||
if (avatarFileId != null) {
|
||||
fileId.add(avatarFileId);
|
||||
logger.info(
|
||||
"[$recentFileID] Updated fileId list with avatarFileId: $fileId",
|
||||
);
|
||||
}
|
||||
} else {
|
||||
logger.info("[$recentFileID] No avatarFaceId provided");
|
||||
}
|
||||
const String queryClusterID = '''
|
||||
SELECT $clusterIDColumn
|
||||
FROM $clusterPersonTable
|
||||
WHERE $personIdColumn = ?
|
||||
''';
|
||||
logger.info(
|
||||
"[$recentFileID] Executing cluster query for personID: $personID",
|
||||
);
|
||||
|
||||
final clusterRows = await db.getAll(
|
||||
queryClusterID,
|
||||
[personID],
|
||||
);
|
||||
logger.info(
|
||||
"[$recentFileID] Found ${clusterRows.length} cluster rows: $clusterRows",
|
||||
);
|
||||
|
||||
final clusterIDs =
|
||||
clusterRows.map((e) => e[clusterIDColumn] as String).toList();
|
||||
logger.info("[$recentFileID] Extracted clusterIDs: $clusterIDs");
|
||||
|
||||
final faceQuery = '''
|
||||
final List<Map<String, dynamic>> faceMaps = await db.getAll(
|
||||
'''
|
||||
SELECT * FROM $facesTable
|
||||
WHERE $faceIDColumn IN (
|
||||
SELECT $faceIDColumn
|
||||
@@ -366,193 +351,45 @@ class MLDataDB with SqlDbBase implements IMLDataDB<int> {
|
||||
)
|
||||
AND $fileIDColumn IN (${List.filled(fileId.length, '?').join(',')})
|
||||
ORDER BY $faceScore DESC
|
||||
''';
|
||||
final queryParams = [...clusterIDs, ...fileId];
|
||||
|
||||
logger.info(
|
||||
"[$recentFileID] Executing face query with ${clusterIDs.length} clusterIDs and ${fileId.length} fileIDs",
|
||||
''',
|
||||
[...clusterIDs, ...fileId],
|
||||
);
|
||||
logger.info("[$recentFileID] Face query: $faceQuery");
|
||||
logger.info("[$recentFileID] Query parameters: $queryParams");
|
||||
|
||||
final List<Map<String, dynamic>> faceMaps = await db.getAll(
|
||||
faceQuery,
|
||||
queryParams,
|
||||
);
|
||||
logger.info("[$recentFileID] Found ${faceMaps.length} face maps");
|
||||
if (faceMaps.isNotEmpty) {
|
||||
logger.info(
|
||||
"[$recentFileID] Found ${faceMaps.length} faces, processing selection",
|
||||
);
|
||||
if (avatarFileId != null) {
|
||||
logger.info(
|
||||
"[$recentFileID] Looking for face with avatarFileId: $avatarFileId",
|
||||
);
|
||||
final row = faceMaps.firstWhereOrNull(
|
||||
(element) => (element[fileIDColumn] as int) == avatarFileId,
|
||||
);
|
||||
if (row != null) {
|
||||
logger.info(
|
||||
"[$recentFileID] Found avatar face, returning: ${row[faceIDColumn]}",
|
||||
);
|
||||
final face = mapRowToFace(row);
|
||||
logger.info(
|
||||
"[$recentFileID] getCoverFaceForPerson SUCCESS (avatar): returning face ${face.faceID}",
|
||||
);
|
||||
return face;
|
||||
} else {
|
||||
logger.info(
|
||||
"[$recentFileID] Avatar face not found in results, falling back to first face",
|
||||
);
|
||||
return mapRowToFace(row);
|
||||
}
|
||||
}
|
||||
logger.info(
|
||||
"[$recentFileID] Returning first face: ${faceMaps.first[faceIDColumn]}",
|
||||
);
|
||||
final face = mapRowToFace(faceMaps.first);
|
||||
logger.info(
|
||||
"[$recentFileID] getCoverFaceForPerson SUCCESS (first): returning face ${face.faceID}",
|
||||
);
|
||||
return face;
|
||||
} else {
|
||||
// Diagnostic queries to understand why faceMaps is empty
|
||||
logger.info(
|
||||
"[$recentFileID] faceMaps is empty, running diagnostic queries",
|
||||
);
|
||||
|
||||
// Test 1: Check if faces exist in faceClustersTable for these clusterIDs
|
||||
if (clusterIDs.isNotEmpty) {
|
||||
final faceIDsInClusters = await db.getAll(
|
||||
'''
|
||||
SELECT $faceIDColumn
|
||||
FROM $faceClustersTable
|
||||
WHERE $clusterIDColumn IN (${List.filled(clusterIDs.length, '?').join(',')})
|
||||
''',
|
||||
clusterIDs,
|
||||
);
|
||||
logger.info(
|
||||
"[$recentFileID] Found ${faceIDsInClusters.length} faceIDs in faceClustersTable for clusterIDs: ${faceIDsInClusters.map((e) => e[faceIDColumn]).toList()}",
|
||||
);
|
||||
|
||||
// Test 2: Check if any of those faces exist in facesTable
|
||||
if (faceIDsInClusters.isNotEmpty) {
|
||||
final faceIDsFromClusters = faceIDsInClusters
|
||||
.map((e) => e[faceIDColumn] as String)
|
||||
.toList();
|
||||
final facesInFacesTable = await db.getAll(
|
||||
'''
|
||||
SELECT $faceIDColumn, $fileIDColumn
|
||||
FROM $facesTable
|
||||
WHERE $faceIDColumn IN (${List.filled(faceIDsFromClusters.length, '?').join(',')})
|
||||
''',
|
||||
faceIDsFromClusters,
|
||||
);
|
||||
logger.info(
|
||||
"[$recentFileID] Found ${facesInFacesTable.length} faces in facesTable: ${facesInFacesTable.map((e) => '${e[faceIDColumn]}(file:${e[fileIDColumn]})').toList()}",
|
||||
);
|
||||
|
||||
// Test 3: Check if any of those faces are for our target fileIDs
|
||||
final facesForTargetFiles = facesInFacesTable
|
||||
.where(
|
||||
(face) => fileId.contains(face[fileIDColumn] as int),
|
||||
)
|
||||
.toList();
|
||||
logger.info(
|
||||
"[$recentFileID] Found ${facesForTargetFiles.length} faces for target fileIDs $fileId: ${facesForTargetFiles.map((e) => '${e[faceIDColumn]}(file:${e[fileIDColumn]})').toList()}",
|
||||
);
|
||||
} else {
|
||||
logger.info(
|
||||
"[$recentFileID] No faceIDs found in faceClustersTable for these clusterIDs",
|
||||
);
|
||||
}
|
||||
} else {
|
||||
logger.info("[$recentFileID] No clusterIDs to check");
|
||||
}
|
||||
|
||||
// Test 4: Check if there are any faces at all for the target fileIDs
|
||||
final allFacesForFiles = await db.getAll(
|
||||
'''
|
||||
SELECT $faceIDColumn, $fileIDColumn
|
||||
FROM $facesTable
|
||||
WHERE $fileIDColumn IN (${List.filled(fileId.length, '?').join(',')})
|
||||
''',
|
||||
fileId,
|
||||
);
|
||||
logger.info(
|
||||
"[$recentFileID] Found ${allFacesForFiles.length} total faces for fileIDs $fileId: ${allFacesForFiles.map((e) => '${e[faceIDColumn]}(file:${e[fileIDColumn]})').toList()}",
|
||||
);
|
||||
|
||||
if (clusterID == null) {
|
||||
logger.severe(
|
||||
"[$recentFileID] Didn't find any faces for personID $personID in getCoverFaceForPerson. fileID: $fileId, clusterIDs: $clusterIDs",
|
||||
);
|
||||
} else {
|
||||
logger.info(
|
||||
"[$recentFileID] No faces found for personID, but clusterID provided, will try clusterID path",
|
||||
);
|
||||
}
|
||||
return mapRowToFace(faceMaps.first);
|
||||
}
|
||||
}
|
||||
if (clusterID != null) {
|
||||
logger.info("[$recentFileID] Processing clusterID path: $clusterID");
|
||||
const String queryFaceID = '''
|
||||
SELECT $faceIDColumn
|
||||
FROM $faceClustersTable
|
||||
WHERE $clusterIDColumn = ?
|
||||
''';
|
||||
logger.info(
|
||||
"[$recentFileID] Executing faceID query for clusterID: $clusterID",
|
||||
);
|
||||
logger.info("[$recentFileID] Query: $queryFaceID");
|
||||
|
||||
final List<Map<String, dynamic>> faceMaps = await db.getAll(
|
||||
queryFaceID,
|
||||
[clusterID],
|
||||
);
|
||||
logger.info(
|
||||
"[$recentFileID] Found ${faceMaps.length} face mappings for cluster: ${faceMaps.map((e) => e[faceIDColumn]).toList()}",
|
||||
);
|
||||
|
||||
final List<Face>? faces = await getFacesForGivenFileID(recentFileID);
|
||||
logger.info(
|
||||
"[$recentFileID] getFacesForGivenFileID returned ${faces?.length ?? 0} faces: ${faces?.map((f) => f.faceID).toList() ?? []}",
|
||||
);
|
||||
|
||||
if (faces != null) {
|
||||
logger.info(
|
||||
"[$recentFileID] Searching for matching face in ${faces.length} faces",
|
||||
);
|
||||
for (final face in faces) {
|
||||
final isMatch = faceMaps.any(
|
||||
if (faceMaps.any(
|
||||
(element) => (element[faceIDColumn] as String) == face.faceID,
|
||||
);
|
||||
logger.info(
|
||||
"[$recentFileID] Checking face ${face.faceID}: match=$isMatch",
|
||||
);
|
||||
if (isMatch) {
|
||||
logger.info(
|
||||
"[$recentFileID] getCoverFaceForPerson SUCCESS (cluster): returning face ${face.faceID}",
|
||||
);
|
||||
)) {
|
||||
return face;
|
||||
}
|
||||
}
|
||||
logger.info(
|
||||
"[$recentFileID] No matching faces found in file for clusterID",
|
||||
);
|
||||
} else {
|
||||
logger.severe(
|
||||
"[$recentFileID] Didn't find any faces for clusterID $clusterID in getCoverFaceForPerson. faces: $faces",
|
||||
);
|
||||
}
|
||||
}
|
||||
if (personID == null && clusterID == null) {
|
||||
logger
|
||||
.severe("[$recentFileID] personID and clusterID cannot be null both");
|
||||
throw Exception("personID and clusterID cannot be null");
|
||||
}
|
||||
logger.severe(
|
||||
"[$recentFileID] getCoverFaceForPerson FAILED: No face found (personID: $personID, clusterID: $clusterID)",
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1417,6 +1254,121 @@ class MLDataDB with SqlDbBase implements IMLDataDB<int> {
|
||||
return embeddings;
|
||||
}
|
||||
|
||||
Future<void> checkMigrateFillClipVectorDB({bool force = false}) async {
|
||||
_logger.info("Waiting for ClipVectorDB to be ready");
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
_logger.info("Checking if ClipVectorDB migration is needed");
|
||||
|
||||
// Check if vector DB migration has run
|
||||
_logger.info("Checking if ClipVectorDB migration has run");
|
||||
final documentsDirectory = await getApplicationDocumentsDirectory();
|
||||
final migrationFlagFile =
|
||||
File(join(documentsDirectory.path, 'clip_vector_migration_done'));
|
||||
if (await migrationFlagFile.exists() && !force) {
|
||||
_logger.info("ClipVectorDB migration not needed, already done");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get total count first to track progress
|
||||
_logger.info("Getting total count of clip embeddings");
|
||||
final db = await instance.asyncDB;
|
||||
final countResult =
|
||||
await db.getAll('SELECT COUNT($fileIDColumn) as total FROM $clipTable');
|
||||
final totalCount = countResult.first['total'] as int;
|
||||
if (totalCount == 0) {
|
||||
_logger.info("No clip embeddings to migrate");
|
||||
await migrationFlagFile.create();
|
||||
return;
|
||||
}
|
||||
_logger.info("Total count of clip embeddings: $totalCount");
|
||||
|
||||
_logger.info("First time referencing ClipVectorDB in migration");
|
||||
final clipVectorDB = ClipVectorDB.instance;
|
||||
_logger.info("ClipVectorDB referenced");
|
||||
await clipVectorDB.deleteAllEmbeddings();
|
||||
_logger.info("ClipVectorDB all embeddings cleared");
|
||||
|
||||
_logger
|
||||
.info("Starting migration of $totalCount clip embeddings to vector DB");
|
||||
const batchSize = 1000;
|
||||
int offset = 0;
|
||||
int processedCount = 0;
|
||||
int weirdCount = 0;
|
||||
int whileCount = 0;
|
||||
final stopwatch = Stopwatch()..start();
|
||||
try {
|
||||
while (true) {
|
||||
whileCount++;
|
||||
_logger.info("$whileCount st round of while loop");
|
||||
// Allow some time for any GC to finish
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
|
||||
_logger.info("Reading $batchSize rows from DB");
|
||||
final List<Map<String, dynamic>> results = await db.getAll('''
|
||||
SELECT $fileIDColumn, $embeddingColumn
|
||||
FROM $clipTable
|
||||
ORDER BY $fileIDColumn DESC
|
||||
LIMIT $batchSize OFFSET $offset
|
||||
''');
|
||||
_logger.info("Got ${results.length} results from DB");
|
||||
if (results.isEmpty) {
|
||||
_logger.info("No more results, breaking out of while loop");
|
||||
break;
|
||||
}
|
||||
_logger.info("Processing ${results.length} results");
|
||||
final List<int> fileIDs = [];
|
||||
final List<Float32List> embeddings = [];
|
||||
for (final result in results) {
|
||||
final embedding =
|
||||
Float32List.view((result[embeddingColumn] as Uint8List).buffer);
|
||||
if (embedding.length == 512) {
|
||||
fileIDs.add(result[fileIDColumn] as int);
|
||||
embeddings.add(Float32List.view(result[embeddingColumn].buffer));
|
||||
} else {
|
||||
weirdCount++;
|
||||
}
|
||||
}
|
||||
_logger.info(
|
||||
"Got ${fileIDs.length} valid embeddings, $weirdCount weird embeddings",
|
||||
);
|
||||
|
||||
await ClipVectorDB.instance
|
||||
.bulkInsertEmbeddings(fileIDs: fileIDs, embeddings: embeddings);
|
||||
_logger.info("Inserted ${fileIDs.length} embeddings to ClipVectorDB");
|
||||
processedCount += fileIDs.length;
|
||||
offset += batchSize;
|
||||
_logger.info(
|
||||
"migrated $processedCount/$totalCount embeddings to ClipVectorDB",
|
||||
);
|
||||
if (processedCount >= totalCount) {
|
||||
_logger.info("All embeddings migrated, breaking out of while loop");
|
||||
break;
|
||||
}
|
||||
_logger.info("Clearing out embeddings and fileIDs");
|
||||
embeddings.clear();
|
||||
fileIDs.clear();
|
||||
results.clear();
|
||||
// Allow some time for any GC to finish
|
||||
_logger.info("Waiting for 100ms for GC to finish");
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
}
|
||||
_logger.info(
|
||||
"migrated all $totalCount embeddings to ClipVectorDB in ${stopwatch.elapsed.inMilliseconds} ms, with $weirdCount weird embeddings not migrated",
|
||||
);
|
||||
await migrationFlagFile.create();
|
||||
_logger.info("ClipVectorDB migration done, flag file created");
|
||||
} catch (e) {
|
||||
_logger.severe(
|
||||
"Error migrating ClipVectorDB after ${stopwatch.elapsed.inMilliseconds} ms, clearing out DB again",
|
||||
e,
|
||||
);
|
||||
await clipVectorDB.deleteAllEmbeddings();
|
||||
rethrow;
|
||||
} finally {
|
||||
stopwatch.stop();
|
||||
}
|
||||
}
|
||||
|
||||
// Get indexed FileIDs
|
||||
@override
|
||||
Future<Map<int, int>> clipIndexedFileWithVersion() async {
|
||||
@@ -1450,12 +1402,25 @@ class MLDataDB with SqlDbBase implements IMLDataDB<int> {
|
||||
'INSERT OR REPLACE INTO $clipTable ($fileIDColumn, $embeddingColumn, $mlVersionColumn) VALUES (?, ?, ?)',
|
||||
_getRowFromEmbedding(embeddings.first),
|
||||
);
|
||||
if (flagService.enableVectorDb) {
|
||||
await ClipVectorDB.instance.insertEmbedding(
|
||||
fileID: embeddings.first.fileID,
|
||||
embedding: embeddings.first.embedding,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
final inputs = embeddings.map((e) => _getRowFromEmbedding(e)).toList();
|
||||
await db.executeBatch(
|
||||
'INSERT OR REPLACE INTO $clipTable ($fileIDColumn, $embeddingColumn, $mlVersionColumn) values(?, ?, ?)',
|
||||
inputs,
|
||||
);
|
||||
if (flagService.enableVectorDb) {
|
||||
await ClipVectorDB.instance.bulkInsertEmbeddings(
|
||||
fileIDs: embeddings.map((e) => e.fileID).toList(),
|
||||
embeddings:
|
||||
embeddings.map((e) => Float32List.fromList(e.embedding)).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
Bus.instance.fire(EmbeddingUpdatedEvent());
|
||||
}
|
||||
@@ -1466,6 +1431,9 @@ class MLDataDB with SqlDbBase implements IMLDataDB<int> {
|
||||
await db.execute(
|
||||
'DELETE FROM $clipTable WHERE $fileIDColumn IN (${fileIDs.join(", ")})',
|
||||
);
|
||||
if (flagService.enableVectorDb) {
|
||||
await ClipVectorDB.instance.deleteEmbeddings(fileIDs);
|
||||
}
|
||||
Bus.instance.fire(EmbeddingUpdatedEvent());
|
||||
}
|
||||
|
||||
@@ -1473,6 +1441,9 @@ class MLDataDB with SqlDbBase implements IMLDataDB<int> {
|
||||
Future<void> deleteClipIndexes() async {
|
||||
final db = await instance.asyncDB;
|
||||
await db.execute('DELETE FROM $clipTable');
|
||||
if (flagService.enableVectorDb) {
|
||||
await ClipVectorDB.instance.deleteAllEmbeddings();
|
||||
}
|
||||
Bus.instance.fire(EmbeddingUpdatedEvent());
|
||||
}
|
||||
|
||||
|
||||
@@ -42,22 +42,20 @@ final lightThemeData = ThemeData(
|
||||
bodyLarge: const TextStyle(color: Colors.orange),
|
||||
),
|
||||
cardColor: const Color.fromRGBO(250, 250, 250, 1.0),
|
||||
dialogTheme: const DialogThemeData(
|
||||
backgroundColor: Color.fromRGBO(250, 250, 250, 1.0), //
|
||||
titleTextStyle: TextStyle(
|
||||
dialogTheme: const DialogTheme().copyWith(
|
||||
backgroundColor: const Color.fromRGBO(250, 250, 250, 1.0), //
|
||||
titleTextStyle: const TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
contentTextStyle: TextStyle(
|
||||
contentTextStyle: const TextStyle(
|
||||
fontFamily: 'Inter-Medium',
|
||||
color: Colors.black,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||
),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
),
|
||||
inputDecorationTheme: const InputDecorationTheme().copyWith(
|
||||
focusedBorder: const UnderlineInputBorder(
|
||||
@@ -119,22 +117,20 @@ final darkThemeData = ThemeData(
|
||||
elevation: 0,
|
||||
),
|
||||
cardColor: const Color.fromRGBO(10, 15, 15, 1.0),
|
||||
dialogTheme: const DialogThemeData(
|
||||
backgroundColor: Color.fromRGBO(15, 15, 15, 1.0),
|
||||
titleTextStyle: TextStyle(
|
||||
dialogTheme: const DialogTheme().copyWith(
|
||||
backgroundColor: const Color.fromRGBO(15, 15, 15, 1.0),
|
||||
titleTextStyle: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
contentTextStyle: TextStyle(
|
||||
contentTextStyle: const TextStyle(
|
||||
fontFamily: 'Inter-Medium',
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||
),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
),
|
||||
inputDecorationTheme: const InputDecorationTheme().copyWith(
|
||||
focusedBorder: const UnderlineInputBorder(
|
||||
@@ -210,7 +206,7 @@ TextTheme _buildTextTheme(Color textColor) {
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
bodySmall: TextStyle(
|
||||
color: textColor.withValues(alpha: 0.6),
|
||||
color: textColor.withOpacity(0.6),
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
@@ -282,7 +278,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
|
||||
@@ -293,7 +289,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)
|
||||
@@ -304,20 +300,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)
|
||||
@@ -340,8 +336,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);
|
||||
|
||||
EnteTheme get enteTheme =>
|
||||
brightness == Brightness.light ? lightTheme : darkTheme;
|
||||
|
||||
@@ -37,27 +37,32 @@ class CenterBox extends $pb.GeneratedMessage {
|
||||
return $result;
|
||||
}
|
||||
CenterBox._() : super();
|
||||
factory CenterBox.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory CenterBox.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
factory CenterBox.fromBuffer($core.List<$core.int> i,
|
||||
[$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
|
||||
create()..mergeFromBuffer(i, r);
|
||||
factory CenterBox.fromJson($core.String i,
|
||||
[$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
|
||||
create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'CenterBox', package: const $pb.PackageName(_omitMessageNames ? '' : 'ente.common'), createEmptyInstance: create)
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||
_omitMessageNames ? '' : 'CenterBox',
|
||||
package: const $pb.PackageName(_omitMessageNames ? '' : 'ente.common'),
|
||||
createEmptyInstance: create)
|
||||
..a<$core.double>(1, _omitFieldNames ? '' : 'x', $pb.PbFieldType.OF)
|
||||
..a<$core.double>(2, _omitFieldNames ? '' : 'y', $pb.PbFieldType.OF)
|
||||
..a<$core.double>(3, _omitFieldNames ? '' : 'height', $pb.PbFieldType.OF)
|
||||
..a<$core.double>(4, _omitFieldNames ? '' : 'width', $pb.PbFieldType.OF)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
..hasRequiredFields = false;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
@$core.Deprecated('Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
CenterBox clone() => CenterBox()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
CenterBox copyWith(void Function(CenterBox) updates) => super.copyWith((message) => updates(message as CenterBox)) as CenterBox;
|
||||
@$core.Deprecated('Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
CenterBox copyWith(void Function(CenterBox) updates) =>
|
||||
super.copyWith((message) => updates(message as CenterBox)) as CenterBox;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@@ -66,13 +71,17 @@ class CenterBox extends $pb.GeneratedMessage {
|
||||
CenterBox createEmptyInstance() => create();
|
||||
static $pb.PbList<CenterBox> createRepeated() => $pb.PbList<CenterBox>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static CenterBox getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CenterBox>(create);
|
||||
static CenterBox getDefault() =>
|
||||
_defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CenterBox>(create);
|
||||
static CenterBox? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.double get x => $_getN(0);
|
||||
@$pb.TagNumber(1)
|
||||
set x($core.double v) { $_setFloat(0, v); }
|
||||
set x($core.double v) {
|
||||
$_setFloat(0, v);
|
||||
}
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasX() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
@@ -81,7 +90,10 @@ class CenterBox extends $pb.GeneratedMessage {
|
||||
@$pb.TagNumber(2)
|
||||
$core.double get y => $_getN(1);
|
||||
@$pb.TagNumber(2)
|
||||
set y($core.double v) { $_setFloat(1, v); }
|
||||
set y($core.double v) {
|
||||
$_setFloat(1, v);
|
||||
}
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasY() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
@@ -90,7 +102,10 @@ class CenterBox extends $pb.GeneratedMessage {
|
||||
@$pb.TagNumber(3)
|
||||
$core.double get height => $_getN(2);
|
||||
@$pb.TagNumber(3)
|
||||
set height($core.double v) { $_setFloat(2, v); }
|
||||
set height($core.double v) {
|
||||
$_setFloat(2, v);
|
||||
}
|
||||
|
||||
@$pb.TagNumber(3)
|
||||
$core.bool hasHeight() => $_has(2);
|
||||
@$pb.TagNumber(3)
|
||||
@@ -99,13 +114,16 @@ class CenterBox extends $pb.GeneratedMessage {
|
||||
@$pb.TagNumber(4)
|
||||
$core.double get width => $_getN(3);
|
||||
@$pb.TagNumber(4)
|
||||
set width($core.double v) { $_setFloat(3, v); }
|
||||
set width($core.double v) {
|
||||
$_setFloat(3, v);
|
||||
}
|
||||
|
||||
@$pb.TagNumber(4)
|
||||
$core.bool hasWidth() => $_has(3);
|
||||
@$pb.TagNumber(4)
|
||||
void clearWidth() => clearField(4);
|
||||
}
|
||||
|
||||
|
||||
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
|
||||
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
|
||||
const _omitMessageNames =
|
||||
$core.bool.fromEnvironment('protobuf.omit_message_names');
|
||||
|
||||
@@ -8,4 +8,3 @@
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
|
||||
@@ -35,4 +35,3 @@ final $typed_data.Uint8List centerBoxDescriptor = $convert.base64Decode(
|
||||
'CglDZW50ZXJCb3gSEQoBeBgBIAEoAkgAUgF4iAEBEhEKAXkYAiABKAJIAVIBeYgBARIbCgZoZW'
|
||||
'lnaHQYAyABKAJIAlIGaGVpZ2h0iAEBEhkKBXdpZHRoGAQgASgCSANSBXdpZHRoiAEBQgQKAl94'
|
||||
'QgQKAl95QgkKB19oZWlnaHRCCAoGX3dpZHRo');
|
||||
|
||||
|
||||
@@ -11,4 +11,3 @@
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
export 'box.pb.dart';
|
||||
|
||||
|
||||
@@ -29,25 +29,30 @@ class EPoint extends $pb.GeneratedMessage {
|
||||
return $result;
|
||||
}
|
||||
EPoint._() : super();
|
||||
factory EPoint.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory EPoint.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
factory EPoint.fromBuffer($core.List<$core.int> i,
|
||||
[$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
|
||||
create()..mergeFromBuffer(i, r);
|
||||
factory EPoint.fromJson($core.String i,
|
||||
[$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
|
||||
create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'EPoint', package: const $pb.PackageName(_omitMessageNames ? '' : 'ente.common'), createEmptyInstance: create)
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||
_omitMessageNames ? '' : 'EPoint',
|
||||
package: const $pb.PackageName(_omitMessageNames ? '' : 'ente.common'),
|
||||
createEmptyInstance: create)
|
||||
..a<$core.double>(1, _omitFieldNames ? '' : 'x', $pb.PbFieldType.OF)
|
||||
..a<$core.double>(2, _omitFieldNames ? '' : 'y', $pb.PbFieldType.OF)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
..hasRequiredFields = false;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
@$core.Deprecated('Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
EPoint clone() => EPoint()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
EPoint copyWith(void Function(EPoint) updates) => super.copyWith((message) => updates(message as EPoint)) as EPoint;
|
||||
@$core.Deprecated('Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
EPoint copyWith(void Function(EPoint) updates) =>
|
||||
super.copyWith((message) => updates(message as EPoint)) as EPoint;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@@ -56,13 +61,17 @@ class EPoint extends $pb.GeneratedMessage {
|
||||
EPoint createEmptyInstance() => create();
|
||||
static $pb.PbList<EPoint> createRepeated() => $pb.PbList<EPoint>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static EPoint getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<EPoint>(create);
|
||||
static EPoint getDefault() =>
|
||||
_defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<EPoint>(create);
|
||||
static EPoint? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.double get x => $_getN(0);
|
||||
@$pb.TagNumber(1)
|
||||
set x($core.double v) { $_setFloat(0, v); }
|
||||
set x($core.double v) {
|
||||
$_setFloat(0, v);
|
||||
}
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasX() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
@@ -71,13 +80,16 @@ class EPoint extends $pb.GeneratedMessage {
|
||||
@$pb.TagNumber(2)
|
||||
$core.double get y => $_getN(1);
|
||||
@$pb.TagNumber(2)
|
||||
set y($core.double v) { $_setFloat(1, v); }
|
||||
set y($core.double v) {
|
||||
$_setFloat(1, v);
|
||||
}
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasY() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearY() => clearField(2);
|
||||
}
|
||||
|
||||
|
||||
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
|
||||
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
|
||||
const _omitMessageNames =
|
||||
$core.bool.fromEnvironment('protobuf.omit_message_names');
|
||||
|
||||
@@ -8,4 +8,3 @@
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user