Compare commits

...

127 Commits

Author SHA1 Message Date
laurenspriem
9386587851 Bumpy version fo rinternal build 2025-07-22 22:37:19 +02:00
laurenspriem
e5f9264164 Bump for internal release 2025-07-21 22:36:54 +02:00
laurenspriem
fcc6354bdc Bump for internal release 2025-07-21 22:14:06 +02:00
laurenspriem
356407a3c2 Bump for internal release 2025-07-21 16:15:36 +02:00
Prateek Sunal
0d61397d51 chore: bump lock 2025-07-21 18:55:53 +05:30
Prateek Sunal
93f464507d Merge remote-tracking branch 'origin/smart-album' into internal_photos_july_25 2025-07-21 18:55:40 +05:30
Prateek Sunal
ae1e435d77 Merge remote-tracking branch 'origin/main' into smart-album 2025-07-21 18:55:26 +05:30
Prateek Sunal
2894bd2386 Merge remote-tracking branch 'origin/smart-album' into internal_photos_july_25 2025-07-21 18:55:13 +05:30
Prateek Sunal
3addc83c14 fix: don't use isolate for now 2025-07-21 18:46:16 +05:30
Prateek Sunal
5b47f69d93 fix: save remote_id and updatedAt as well 2025-07-21 18:46:00 +05:30
Prateek Sunal
1c02064211 fix: dialog time 2025-07-21 18:45:40 +05:30
Prateek Sunal
ba01e2d181 chore: update locks 2025-07-21 17:30:40 +05:30
Prateek Sunal
fdfc155add chore: update locks 2025-07-21 17:28:38 +05:30
Prateek Sunal
3c5a29b0ab fix: popup menu item & smart people selection 2025-07-21 17:28:32 +05:30
Prateek Sunal
fa65a993c0 Merge branch 'flutter-upgrade' into smart-album 2025-07-21 15:40:27 +05:30
Prateek Sunal
4ff77067dc chore: update flutter version for auth build 2025-07-21 00:36:21 +05:30
Prateek Sunal
437b3d028a chore: update locks 2025-07-21 00:34:27 +05:30
Prateek Sunal
234daac3b8 chore: update lock file 2025-07-21 00:30:30 +05:30
Prateek Sunal
f433040aaf Merge remote-tracking branch 'origin/face_thumbnail_logging' into internal_photos_july_25 2025-07-21 00:29:54 +05:30
Prateek Sunal
b841666f5d Merge branch 'smart-album' into internal_photos_july_25 2025-07-21 00:28:49 +05:30
Prateek Sunal
418d20b336 Merge branch 'isolated-ffmpeg' into smart-album 2025-07-21 00:23:36 +05:30
Prateek Sunal
8afc4bb0cb fix: switch to old version lock 2025-07-21 00:23:24 +05:30
Prateek Sunal
ecd3ce850f chore: update lock file 2025-07-21 00:04:34 +05:30
Prateek Sunal
bc61727e8b Merge branch 'flutter-upgrade' into isolated-ffmpeg 2025-07-21 00:04:06 +05:30
Prateek Sunal
32f987e551 chore: downgrade to 3.29.3 2025-07-21 00:03:27 +05:30
Prateek Sunal
3596d0e42d fix: downgrade flutter upgrade to 3.29.3 2025-07-21 00:02:34 +05:30
Prateek Sunal
4d9b6ecbc6 fix: use existing progress dialog 2025-07-18 17:10:40 +05:30
Prateek Sunal
d7f019c4f5 fix: better decode of SmartAlbumConfig 2025-07-18 16:35:23 +05:30
Prateek Sunal
20d498722b chore: bump correctly 2025-07-16 18:54:38 +05:30
Prateek Sunal
5423bde48a chore: bump version 2025-07-16 18:38:13 +05:30
Prateek Sunal
794aa39441 Merge remote-tracking branch 'origin/smart-album' into internal_photos_july_25 2025-07-16 18:36:17 +05:30
Prateek Sunal
4f1db7f001 fix: track if bg properly 2025-07-16 18:35:58 +05:30
Prateek Sunal
ab96fdb379 fix: don't fetch files based on collection id 2025-07-16 18:22:35 +05:30
Prateek Sunal
90650995f7 fix: use correct method to remove files from collection 2025-07-16 18:21:38 +05:30
Prateek Sunal
f83cd57b6f fix: try to add remove people dialog popup 2025-07-16 18:17:08 +05:30
Prateek Sunal
f0273def2f fix: handle duplicate case 2025-07-16 17:21:36 +05:30
laurenspriem
4c4a1991ca Bump version 2025-07-16 13:23:10 +02:00
laurenspriem
6762d5b426 Merge branch 'main' into face_thumbnail_logging 2025-07-16 13:19:41 +02:00
Prateek Sunal
d4e2317816 fix: update merge function to updatedAt 2025-07-16 16:48:03 +05:30
Prateek Sunal
2040044994 chore: add note 2025-07-16 16:24:42 +05:30
Prateek Sunal
a3ee242faa fix: pass remote id 2025-07-16 16:13:06 +05:30
Prateek Sunal
78f2bb0d7d fix: add option in overflow & other fixes 2025-07-16 16:00:52 +05:30
Prateek Sunal
b723b7daf0 fix: revamp and use EntityService 2025-07-16 12:47:13 +05:30
laurenspriem
6e7ee1fa16 Extra logging from FileFaceWidget 2025-07-15 21:59:38 +02:00
laurenspriem
6ef9e0fdb0 More aggressive error logging for PersonFaceWidget 2025-07-15 21:22:07 +02:00
Prateek Sunal
e2e0436830 fix: issues 2025-07-15 19:57:41 +05:30
Prateek Sunal
dea67250c8 fix: selection bug + initial empty files bug 2025-07-15 19:26:27 +05:30
Prateek Sunal
dc2246aa47 chore: renaming things 2025-07-15 16:55:54 +05:30
Prateek Sunal
adb1c96ce6 fix: remove shared preferences instance call 2025-07-15 16:21:42 +05:30
Prateek Sunal
c413111768 fix: don't show close button in people selection page 2025-07-15 16:20:31 +05:30
Prateek Sunal
6d6cd91b22 fix: optimize things (1) 2025-07-15 16:19:11 +05:30
Prateek Sunal
3708a347f5 feat: init smart albums concept 2025-07-14 18:05:58 +05:30
Prateek Sunal
ac802f022c Merge remote-tracking branch 'origin/isolated-ffmpeg' into internal_photos_july_25 2025-07-14 14:47:49 +05:30
Prateek Sunal
99d84a1154 fix: remove log level 2025-07-14 14:43:00 +05:30
Prateek Sunal
126a96326f fix: don't use computer for ffmpeg isolate 2025-07-14 11:59:55 +05:30
Prateek Sunal
b7ead2004a fix: do isolate things without combine package 2025-07-14 11:39:25 +05:30
Prateek Sunal
87fad99863 Merge remote-tracking branch 'origin/flutter-upgrade' into isolated-ffmpeg 2025-07-14 09:00:19 +05:30
Prateek Sunal
9f727bb95d feat: upgrade auth to flutter 3.32 2025-07-11 20:28:43 +05:30
Prateek Sunal
b8ecf0f42f chore: bump version 2025-07-11 16:12:10 +05:30
Prateek Sunal
0de2afe0fe Merge branch 'isolated-ffmpeg' into internal_photos_july_25 2025-07-11 16:11:04 +05:30
Prateek Sunal
bd42a4d1f6 Merge branch 'flutter-upgrade' into isolated-ffmpeg 2025-07-11 16:10:32 +05:30
Prateek Sunal
22e0cd2168 chore: update locks 2025-07-11 16:09:53 +05:30
Prateek Sunal
0662baac73 Merge remote-tracking branch 'origin/main' into flutter-upgrade 2025-07-11 16:09:12 +05:30
Prateek Sunal
ef3c561cf1 fix: no log output 2025-07-11 15:27:28 +05:30
Prateek Sunal
45c231b9d0 Merge remote-tracking branch 'origin/isolated-ffmpeg' into internal_photos_july_25 2025-07-11 12:31:26 +05:30
Prateek Sunal
6f07399b5a Merge remote-tracking branch 'origin/flutter-upgrade' into isolated-ffmpeg 2025-07-11 12:31:11 +05:30
Prateek Sunal
8524742c92 Merge remote-tracking branch 'origin/main' into flutter-upgrade 2025-07-11 12:30:56 +05:30
Prateek Sunal
51496ee148 chore: bump version 2025-07-11 12:08:19 +05:30
Prateek Sunal
385f52de0f chore: bump again 2025-07-11 12:06:46 +05:30
Prateek Sunal
974482a442 chore: bump version 2025-07-11 12:04:56 +05:30
Prateek Sunal
8a90aee4a0 Merge remote-tracking branch 'origin/isolated-ffmpeg' into internal_photos_july_25 2025-07-10 19:04:47 +05:30
Prateek Sunal
9125090a3d fix: bg changes 2025-07-10 19:04:32 +05:30
Prateek Sunal
848fae73b4 Merge remote-tracking branch 'origin/isolated-ffmpeg' into internal_photos_july_25 2025-07-10 18:54:04 +05:30
Prateek Sunal
4a552fbcb4 Merge remote-tracking branch 'origin/flutter-upgrade' into isolated-ffmpeg 2025-07-10 18:53:46 +05:30
Prateek Sunal
85ef085084 chore: lint fix 2025-07-10 18:53:23 +05:30
Prateek Sunal
f1d128f6b0 Merge remote-tracking branch 'origin/main' into flutter-upgrade 2025-07-10 18:53:07 +05:30
Prateek Sunal
c925ed2117 fix: issues 2025-07-10 18:52:46 +05:30
Prateek Sunal
142a5f9661 fix: issue 2025-07-10 18:52:36 +05:30
Prateek Sunal
e70b7eb1e8 chore: bump version 2025-07-08 18:48:39 +05:30
Prateek Sunal
ae0c83b1aa Merge branch 'flutter-upgrade' into isolated-ffmpeg 2025-07-08 18:47:50 +05:30
Prateek Sunal
8f1ee2ef15 Merge remote-tracking branch 'origin/main' into flutter-upgrade 2025-07-08 18:47:35 +05:30
Prateek Sunal
f1d978fbf7 fix: use combine for method channel communication 2025-07-08 18:46:51 +05:30
Prateek Sunal
4604280ef8 fix: move ffmpeg and ffprobe to isolate 2025-07-07 18:41:03 +05:30
Prateek Sunal
18ab4060b2 Merge remote-tracking branch 'origin/flutter-upgrade' into isolated-ffmpeg 2025-07-07 13:17:08 +05:30
Prateek Sunal
9a4d465672 chore: update runner scheme 2025-07-07 13:16:49 +05:30
Prateek Sunal
7ea9483cca fix: dependency 2025-07-07 13:10:59 +05:30
Prateek Sunal
d9add4f827 chore: update locks 2025-07-07 11:56:43 +05:30
Prateek Sunal
3c19c00a70 Merge remote-tracking branch 'origin/flutter-upgrade' into isolated-ffmpeg 2025-07-07 11:52:46 +05:30
Prateek Sunal
12c19d1ed1 Merge remote-tracking branch 'origin/main' into flutter-upgrade 2025-07-07 11:52:24 +05:30
Prateek Sunal
c757b837f1 fix: update flutter version in all sources 2025-07-07 11:44:42 +05:30
Prateek Sunal
a9f1c0dbd4 fix: fetch the ffmpeg source at first 2025-07-07 11:42:35 +05:30
Prateek Sunal
896d77a83e fix: upgrade plugins 2025-07-07 11:28:56 +05:30
Prateek Sunal
b1210e1d15 Merge remote-tracking branch 'origin/flutter-upgrade' into isolated-ffmpeg 2025-07-04 16:55:15 +05:30
Prateek Sunal
127df30242 fix: readd workmanager 2025-07-04 16:55:04 +05:30
Prateek Sunal
c0c17af51a Merge remote-tracking branch 'origin/flutter-upgrade' into isolated-ffmpeg 2025-07-04 16:48:16 +05:30
Prateek Sunal
d92ec2276e chore: update lock files 2025-07-04 16:44:43 +05:30
Prateek Sunal
1f99727ab9 fix: update git ignore 2025-07-04 16:43:52 +05:30
Prateek Sunal
85784920a9 fix: remove unwanted files 2025-07-04 16:41:12 +05:30
Prateek Sunal
d7b3af063b Merge remote-tracking branch 'origin/main' into flutter-upgrade 2025-07-04 16:38:37 +05:30
Prateek Sunal
baa3d49d4b fix: add desugaring for flutter_local_notifications to work 2025-06-18 16:00:27 +05:30
Prateek Sunal
d2c2062256 fix: upgeade gradle 2025-06-18 16:00:13 +05:30
Prateek Sunal
c646909765 fix: don't pin collection and path 2025-06-18 14:00:31 +05:30
Prateek Sunal
8b4f03b256 fix: temp commit, to revert 2025-06-17 14:44:25 +05:30
Prateek Sunal
976bd0134c fix: log string 2025-06-17 14:44:16 +05:30
Prateek Sunal
8a785aac8f Merge branch 'flutter-upgrade' into isolated-ffmpeg 2025-06-16 17:21:17 +05:30
Prateek Sunal
452812af11 chore(ios): update lock files 2025-06-16 17:18:49 +05:30
Prateek Sunal
44fb8fec1a Merge remote-tracking branch 'origin/main' into flutter-upgrade 2025-06-16 17:17:55 +05:30
Prateek Sunal
1d8fc7aba8 fix: revert back to old l10n 2025-06-16 17:08:51 +05:30
Prateek Sunal
654db76175 fix: format files 2025-06-16 17:06:50 +05:30
Prateek Sunal
364170f38d fix: DialogTheme 2025-06-16 17:04:10 +05:30
Prateek Sunal
0cd7c92672 fix: add intl based locals as well 2025-06-16 17:04:02 +05:30
Prateek Sunal
962aaa1b7a Merge remote-tracking branch 'origin/main' into flutter-upgrade 2025-06-16 14:54:37 +05:30
Prateek Sunal
6ec0c550a3 chore: lock deps 2025-06-16 14:53:25 +05:30
Prateek Sunal
b67fcdb9ed fix: map and image editor related issues 2025-06-16 14:46:51 +05:30
Prateek Sunal
2f4c3c7777 feat: upgrade deps (incomplete) 2025-06-16 12:58:13 +05:30
Prateek Sunal
cb84164466 Merge remote-tracking branch 'origin/main' into flutter-upgrade 2025-06-12 18:44:10 +05:30
Prateek Sunal
7b6aed426d Merge remote-tracking branch 'origin/main' into flutter-upgrade 2025-06-12 16:55:23 +05:30
Prateek Sunal
81c539979d Merge remote-tracking branch 'origin/main' into flutter-upgrade 2025-06-06 14:35:39 +05:30
Prateek Sunal
3cffd969b4 feat: bump flutter to 3.29 2025-06-06 14:35:30 +05:30
Prateek Sunal
fbb15adf11 Merge remote-tracking branch 'origin/main' into isolated-ffmpeg 2025-05-02 10:56:28 +05:30
Prateek Sunal
3efd36ab7b fix: statitify things and log error 2025-04-29 00:55:40 +05:30
Prateek Sunal
11cb355e98 fix: remove init from main 2025-04-29 00:54:14 +05:30
Prateek Sunal
caadca9a48 fix: reencode audio as aac 2025-04-29 00:54:04 +05:30
Prateek Sunal
0a50e33023 Merge remote-tracking branch 'origin/main' into isolated-ffmpeg 2025-04-28 13:09:03 +05:30
Prateek Sunal
5eef2a5816 fix: update isolated function 2025-04-28 13:08:42 +05:30
Prateek Sunal
fe4bf5c217 Merge remote-tracking branch 'origin/main' into isolated-ffmpeg 2025-04-28 12:10:47 +05:30
Prateek Sunal
912fc72600 Add ffmpeg framework support and refactor video processing to isolated service 2025-04-17 03:39:59 +05:30
176 changed files with 2447 additions and 1484 deletions

View File

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

View File

@@ -8,7 +8,7 @@ on:
- ".github/workflows/auth-lint.yml"
env:
FLUTTER_VERSION: "3.24.3"
FLUTTER_VERSION: "3.29.3"
permissions:
contents: read

View File

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

View File

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

View File

@@ -4,7 +4,7 @@ on:
workflow_dispatch: # Allow manually running the action
env:
FLUTTER_VERSION: "3.24.3"
FLUTTER_VERSION: "3.29.3"
RUST_VERSION: "1.85.1"
permissions:

View File

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

View File

@@ -8,7 +8,7 @@ on:
- ".github/workflows/mobile-lint.yml"
env:
FLUTTER_VERSION: "3.24.3"
FLUTTER_VERSION: "3.29.3"
permissions:
contents: read

View File

@@ -9,7 +9,7 @@ on:
- "photos-v*"
env:
FLUTTER_VERSION: "3.24.3"
FLUTTER_VERSION: "3.29.3"
permissions:
contents: write

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -40,7 +40,7 @@ class _AppState extends State<App>
late StreamSubscription<SignedOutEvent> _signedOutEvent;
late StreamSubscription<SignedInEvent> _signedInEvent;
Locale? locale;
setLocale(Locale newLocale) {
void setLocale(Locale newLocale) {
setState(() {
locale = newLocale;
});
@@ -82,7 +82,7 @@ class _AppState extends State<App>
UpdateService.instance.getLatestVersionInfo(),
);
},
barrierColor: Colors.black.withOpacity(0.85),
barrierColor: Colors.black.withValues(alpha: 0.85),
);
});
}

View File

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

View File

@@ -39,7 +39,7 @@ final lightThemeData = ThemeData(
bodyLarge: const TextStyle(color: Colors.orange),
),
cardColor: const Color.fromRGBO(250, 250, 250, 1.0),
dialogTheme: const DialogTheme().copyWith(
dialogTheme: const DialogThemeData().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 DialogTheme().copyWith(
dialogTheme: const DialogThemeData().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.withOpacity(0.4),
color: textColor.withValues(alpha: 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).withOpacity(0.75)
? const Color.fromRGBO(0, 0, 0, 1).withValues(alpha: 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).withOpacity(0.1);
: const Color.fromRGBO(255, 255, 255, 1).withValues(alpha: 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).withOpacity(0.8)
: const Color.fromRGBO(255, 255, 255, 1).withOpacity(0.5);
? const Color.fromRGBO(0, 0, 0, 1).withValues(alpha: 0.8)
: const Color.fromRGBO(255, 255, 255, 1).withValues(alpha: 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).withOpacity(0.5)
: const Color.fromRGBO(255, 255, 255, 1).withOpacity(0.5);
? const Color.fromRGBO(0, 0, 0, 1).withValues(alpha: 0.5)
: const Color.fromRGBO(255, 255, 255, 1).withValues(alpha: 0.5);
Color get dotsIndicatorInactiveColor => brightness == Brightness.light
? const Color.fromRGBO(0, 0, 0, 1).withOpacity(0.12)
: const Color.fromRGBO(255, 255, 255, 1).withOpacity(0.12);
? const Color.fromRGBO(0, 0, 0, 1).withValues(alpha: 0.12)
: const Color.fromRGBO(255, 255, 255, 1).withValues(alpha: 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).withOpacity(0.5)
: const Color.fromRGBO(255, 255, 255, 1).withOpacity(0.5);
? const Color.fromRGBO(0, 0, 0, 1).withValues(alpha: 0.5)
: const Color.fromRGBO(255, 255, 255, 1).withValues(alpha: 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.withOpacity(0.32)
: Colors.black.withOpacity(0.64);
? Colors.black.withValues(alpha: 0.32)
: Colors.black.withValues(alpha: 0.64);
Color get codeCardBackgroundColor => brightness == Brightness.light
? const Color.fromRGBO(246, 246, 246, 1)

View File

@@ -1,7 +1,8 @@
import "package:ente_auth/l10n/arb/app_localizations.dart"
show AppLocalizations;
import "package:flutter/widgets.dart";
import "package:flutter_gen/gen_l10n/app_localizations.dart";
export "package:flutter_gen/gen_l10n/app_localizations.dart";
export "package:ente_auth/l10n/arb/app_localizations.dart"
show AppLocalizations;
extension AppLocalizationsX on BuildContext {
AppLocalizations get l10n => AppLocalizations.of(this);

View File

@@ -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 fromMap(Map<String, dynamic>? map) {
if (map == null) return null;
static BillingPlans fromMap(Map<String, dynamic>? map) {
if (map == null) return BillingPlans(plans: [], freePlan: null);
return BillingPlans(
plans: List<BillingPlan>.from(
@@ -49,7 +49,7 @@ class FreePlan {
};
}
static fromMap(Map<String, dynamic>? map) {
static FreePlan? fromMap(Map<String, dynamic>? map) {
if (map == null) return null;
return FreePlan(
@@ -91,7 +91,7 @@ class BillingPlan {
};
}
static fromMap(Map<String, dynamic>? map) {
static BillingPlan? fromMap(Map<String, dynamic>? map) {
if (map == null) return null;
return BillingPlan(

View File

@@ -332,7 +332,7 @@ class _SetupEnterSecretKeyPageState extends State<SetupEnterSecretKeyPage> {
},
);
},
barrierColor: Colors.black.withOpacity(0.85),
barrierColor: Colors.black.withValues(alpha: 0.85),
barrierDismissible: false,
);
},

View File

@@ -75,7 +75,7 @@ class CodeDisplayStore {
builder: (BuildContext context) {
return EditTagDialog(tag: tag);
},
barrierColor: Colors.black.withOpacity(0.85),
barrierColor: Colors.black.withValues(alpha: 0.85),
barrierDismissible: false,
);
}

View File

@@ -147,12 +147,13 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
),
),
child: DottedBorder(
padding: EdgeInsets.zero,
borderType: BorderType.RRect,
strokeWidth: 1,
color: const Color(0xFF6B6B6B),
dashPattern: const [6, 6],
radius: const Radius.circular(8),
options: const RoundedRectDottedBorderOptions(
padding: EdgeInsets.zero,
strokeWidth: 1,
color: Color(0xFF6B6B6B),
dashPattern: [6, 6],
radius: Radius.circular(8),
),
child: SizedBox(
width: double.infinity,
child: Stack(
@@ -314,7 +315,13 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
await _recoveryKeyFile.delete();
}
_recoveryKeyFile.writeAsStringSync(recoveryKey);
await Share.shareXFiles([XFile(_recoveryKeyFile.path)]);
await SharePlus.instance.share(
ShareParams(
files: [
XFile(_recoveryKeyFile.path),
],
),
);
Future.delayed(const Duration(milliseconds: 500), () {
if (mounted) {
setState(() {

View File

@@ -82,7 +82,7 @@ class _SessionsPageState extends State<SessionsPage> {
color: Theme.of(context)
.colorScheme
.onSurface
.withOpacity(0.8),
.withValues(alpha: 0.8),
fontSize: 14,
),
),
@@ -95,7 +95,7 @@ class _SessionsPageState extends State<SessionsPage> {
color: Theme.of(context)
.colorScheme
.onSurface
.withOpacity(0.8),
.withValues(alpha: 0.8),
fontSize: 12,
),
),

View File

@@ -54,12 +54,12 @@ class BannerWidget extends StatelessWidget {
dashColor = const Color.fromRGBO(255, 191, 12, 1);
boxShadow = [
BoxShadow(
color: const Color(0xFFFDB816).withOpacity(0.1),
color: const Color(0xFFFDB816).withValues(alpha: 0.1),
blurRadius: 50,
spreadRadius: 80,
),
BoxShadow(
color: const Color(0xFFFDB816).withOpacity(0.2),
color: const Color(0xFFFDB816).withValues(alpha: 0.2),
blurRadius: 25,
),
];
@@ -71,12 +71,13 @@ class BannerWidget extends StatelessWidget {
dashColor = const Color.fromRGBO(233, 233, 233, 1);
boxShadow = [
BoxShadow(
color: const Color.fromRGBO(78, 78, 78, 1).withOpacity(0.2),
color: const Color.fromRGBO(78, 78, 78, 1).withValues(alpha: 0.2),
blurRadius: 50,
spreadRadius: 100,
),
BoxShadow(
color: const Color.fromRGBO(23, 22, 22, 0.30).withOpacity(0.1),
color:
const Color.fromRGBO(23, 22, 22, 0.30).withValues(alpha: 0.1),
blurRadius: 25,
),
];
@@ -87,12 +88,12 @@ class BannerWidget extends StatelessWidget {
dashColor = const Color.fromRGBO(29, 185, 84, 1);
boxShadow = [
BoxShadow(
color: const Color.fromRGBO(38, 203, 95, 1).withOpacity(0.08),
color: const Color.fromRGBO(38, 203, 95, 1).withValues(alpha: 0.08),
blurRadius: 50,
spreadRadius: 100,
),
BoxShadow(
color: const Color.fromRGBO(0, 0, 0, 0.50).withOpacity(0.08),
color: const Color.fromRGBO(0, 0, 0, 0.50).withValues(alpha: 0.08),
blurRadius: 25,
),
];
@@ -103,12 +104,12 @@ class BannerWidget extends StatelessWidget {
imagePath = "assets/discount.png";
boxShadow = [
BoxShadow(
color: const Color.fromRGBO(38, 203, 95, 1).withOpacity(0.08),
color: const Color.fromRGBO(38, 203, 95, 1).withValues(alpha: 0.08),
blurRadius: 50,
spreadRadius: 100,
),
BoxShadow(
color: const Color.fromRGBO(0, 0, 0, 0.50).withOpacity(0.08),
color: const Color.fromRGBO(0, 0, 0, 0.50).withValues(alpha: 0.08),
blurRadius: 25,
),
];
@@ -121,10 +122,11 @@ class BannerWidget extends StatelessWidget {
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(50)),
child: DottedBorder(
borderType: BorderType.RRect,
radius: const Radius.circular(50),
dashPattern: const <double>[3, 3],
color: dashColor,
options: RoundedRectDottedBorderOptions(
radius: const Radius.circular(50),
dashPattern: <double>[3, 3],
color: dashColor,
),
child: Stack(
children: [
if (BannerType.starUs == type)

View File

@@ -28,7 +28,7 @@ class CustomIconWidget extends StatelessWidget {
width: 1.5,
color: getEnteColorScheme(context)
.tagChipSelectedColor
.withOpacity(0.5),
.withValues(alpha: 0.5),
),
borderRadius: SmoothBorderRadius(
cornerRadius: 15.5,
@@ -102,7 +102,7 @@ class CustomIconWidget extends StatelessWidget {
child: Icon(
Icons.edit,
size: 16,
color: Colors.black.withOpacity(0.9),
color: Colors.black.withValues(alpha: 0.9),
),
),
),

View File

@@ -52,7 +52,7 @@ class NotificationWidget extends StatelessWidget {
subTextStyle = textTheme.miniMuted;
strokeColorScheme = colorScheme;
boxShadow = [
BoxShadow(color: Colors.black.withOpacity(0.25), blurRadius: 1),
BoxShadow(color: Colors.black.withValues(alpha: 0.25), blurRadius: 1),
];
break;

View File

@@ -123,7 +123,7 @@ class TitleBarWidget extends StatelessWidget {
);
}
_actionsWithPaddingInBetween() {
List<Widget> _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) {

View File

@@ -1,6 +1,7 @@
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';
@@ -104,7 +105,7 @@ class _ToggleSwitchWidgetState extends State<ToggleSwitchWidget> {
);
}
Widget _stateIcon(enteColorScheme) {
Widget _stateIcon(EnteColorScheme enteColorScheme) {
if (executionState == ExecutionState.idle) {
return const SizedBox(width: 24);
} else if (executionState == ExecutionState.inProgress) {

View File

@@ -23,7 +23,8 @@ class CoachMarkWidget extends StatelessWidget {
Expanded(
child: Container(
width: double.infinity,
color: Theme.of(context).colorScheme.surface.withOpacity(0.1),
color:
Theme.of(context).colorScheme.surface.withValues(alpha: 0.1),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 8, sigmaY: 8),
child: Row(

View File

@@ -77,7 +77,7 @@ class AboutSectionWidget extends StatelessWidget {
UpdateService.instance.getLatestVersionInfo(),
);
},
barrierColor: Colors.black.withOpacity(0.85),
barrierColor: Colors.black.withValues(alpha: 0.85),
);
} else {
showShortToast(

View File

@@ -56,7 +56,7 @@ class AccountSectionWidget extends StatelessWidget {
builder: (BuildContext context) {
return const ChangeEmailDialog();
},
barrierColor: Colors.black.withOpacity(0.85),
barrierColor: Colors.black.withValues(alpha: 0.85),
barrierDismissible: false,
);
}

View File

@@ -83,7 +83,7 @@ class _DuplicateCodePageState extends State<DuplicateCodePage> {
color: Theme.of(context)
.iconTheme
.color!
.withOpacity(0.7),
.withValues(alpha: 0.7),
),
),
const Padding(padding: EdgeInsets.only(left: 4)),

View File

@@ -170,9 +170,14 @@ Future<void> _exportCodes(
}
codeFile.writeAsStringSync(fileContent);
final Size size = MediaQuery.of(context).size;
await Share.shareXFiles(
[XFile(codeFile.path)],
sharePositionOrigin: Rect.fromLTWH(0, 0, size.width, size.height / 2),
await SharePlus.instance.share(
ShareParams(
files: <XFile>[
XFile(codeFile.path, mimeType: 'text/plain'),
],
sharePositionOrigin:
Rect.fromLTWH(0, 0, size.width, size.height / 2),
),
);
Future.delayed(const Duration(seconds: 30), () async {
if (codeFile.existsSync()) {

View File

@@ -116,10 +116,10 @@ class _LockScreenConfirmPasswordState extends State<LockScreenConfirmPassword> {
shape: BoxShape.circle,
gradient: LinearGradient(
colors: [
Colors.grey.shade500.withOpacity(0.2),
Colors.grey.shade50.withOpacity(0.1),
Colors.grey.shade400.withOpacity(0.2),
Colors.grey.shade300.withOpacity(0.4),
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),
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,

View File

@@ -1,7 +1,9 @@
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";
@@ -89,7 +91,7 @@ class _LockScreenConfirmPinState extends State<LockScreenConfirmPin> {
);
}
Widget _getBody(colorTheme, textTheme) {
Widget _getBody(EnteColorScheme colorTheme, EnteTextTheme textTheme) {
return Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
@@ -107,10 +109,10 @@ class _LockScreenConfirmPinState extends State<LockScreenConfirmPin> {
shape: BoxShape.circle,
gradient: LinearGradient(
colors: [
Colors.grey.shade500.withOpacity(0.2),
Colors.grey.shade50.withOpacity(0.1),
Colors.grey.shade400.withOpacity(0.2),
Colors.grey.shade300.withOpacity(0.4),
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),
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,

View File

@@ -127,10 +127,10 @@ class _LockScreenPasswordState extends State<LockScreenPassword> {
shape: BoxShape.circle,
gradient: LinearGradient(
colors: [
Colors.grey.shade500.withOpacity(0.2),
Colors.grey.shade50.withOpacity(0.1),
Colors.grey.shade400.withOpacity(0.2),
Colors.grey.shade300.withOpacity(0.4),
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),
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,

View File

@@ -178,10 +178,10 @@ class _LockScreenPinState extends State<LockScreenPin> {
shape: BoxShape.circle,
gradient: LinearGradient(
colors: [
Colors.grey.shade500.withOpacity(0.2),
Colors.grey.shade50.withOpacity(0.1),
Colors.grey.shade400.withOpacity(0.2),
Colors.grey.shade300.withOpacity(0.4),
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),
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,

View File

@@ -43,7 +43,7 @@ class _SupportSectionWidgetState extends State<SupportSectionWidget> {
trailingIconIsMuted: true,
onTap: () async {
try {
PlatformUtil.openWebView(
await PlatformUtil.openWebView(
context,
context.l10n.faq,
"https://help.ente.io/auth/faq",

View File

@@ -35,7 +35,7 @@ class SortCodeMenuWidget extends StatelessWidget {
text,
style: Theme.of(context).textTheme.titleMedium!.copyWith(
fontSize: 14,
color: Theme.of(context).iconTheme.color!.withOpacity(0.7),
color: Theme.of(context).iconTheme.color!.withValues(alpha: 0.7),
),
);
}

View File

@@ -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).

View File

@@ -96,10 +96,10 @@ class _LockScreenState extends State<LockScreen> with WidgetsBindingObserver {
shape: BoxShape.circle,
gradient: LinearGradient(
colors: [
Colors.grey.shade500.withOpacity(0.2),
Colors.grey.shade50.withOpacity(0.1),
Colors.grey.shade400.withOpacity(0.2),
Colors.grey.shade300.withOpacity(0.4),
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),
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,

View File

@@ -98,8 +98,9 @@ class _TwoFactorRecoveryPageState extends State<TwoFactorRecoveryPage> {
style: TextStyle(
decoration: TextDecoration.underline,
fontSize: 12,
color:
getEnteColorScheme(context).textBase.withOpacity(0.9),
color: getEnteColorScheme(context)
.textBase
.withValues(alpha: 0.9),
),
),
),

View File

@@ -180,7 +180,7 @@ Future<ButtonResult?> showGenericErrorDialog({
context,
context.l10n.faq,
"https://help.ente.io/auth/troubleshooting/windows-login",
);
).ignore();
},
),
ButtonWidget(

View File

@@ -34,7 +34,7 @@ class DirectoryUtils {
}
static String migratedNamingChanges = "migrated_naming_changes.b5";
static migrateNamingChanges() async {
static Future<void> 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"),

View File

@@ -232,9 +232,13 @@ Future<void> exportLogs(
MimeType.zip,
);
} else {
await Share.shareXFiles(
[XFile(zipFilePath, mimeType: 'application/zip')],
sharePositionOrigin: Rect.fromLTWH(0, 0, size.width, size.height / 2),
await SharePlus.instance.share(
ShareParams(
files: <XFile>[
XFile(zipFilePath, mimeType: 'application/zip'),
],
sharePositionOrigin: Rect.fromLTWH(0, 0, size.width, size.height / 2),
),
);
}
}

View File

@@ -28,7 +28,11 @@ class PlatformUtil {
? cupertinoTextSelectionControls
: desktopTextSelectionControls;
static openWebView(BuildContext context, String title, String url) async {
static Future<void> openWebView(
BuildContext context,
String title,
String url,
) async {
if (PlatformUtil.isDesktop()) {
await launchUrlString(url);
return;

View File

@@ -91,9 +91,11 @@ Future<ShareResult> shareText(
}) async {
try {
final sharePosOrigin = _sharePosOrigin(context, key);
return Share.share(
text,
sharePositionOrigin: sharePosOrigin,
return SharePlus.instance.share(
ShareParams(
text: text,
sharePositionOrigin: sharePosOrigin,
),
);
} catch (e, s) {
Logger("ShareUtil").severe("failed to share text", e, s);

View File

@@ -47,6 +47,6 @@ void showToast(
}
}
void showShortToast(context, String message) {
void showShortToast(BuildContext context, String message) {
showToast(context, message, toastLength: Toast.LENGTH_SHORT);
}

View File

@@ -36,7 +36,7 @@ class WindowsProtocolHandler {
hKey,
txtKey,
txtValue,
REG_VALUE_TYPE.REG_SZ,
REG_SZ,
txtData,
txtData.length * 2 + 2,
);

View File

@@ -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/screen_retriever_plugin.h>
#include <screen_retriever_linux/screen_retriever_linux_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_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin");
screen_retriever_plugin_register_with_registrar(screen_retriever_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) sentry_flutter_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "SentryFlutterPlugin");
sentry_flutter_plugin_register_with_registrar(sentry_flutter_registrar);

View File

@@ -7,7 +7,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
flutter_local_authentication
flutter_secure_storage_linux
gtk
screen_retriever
screen_retriever_linux
sentry_flutter
sodium_libs
sqlite3_flutter_libs

View File

@@ -8,6 +8,7 @@ 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
@@ -16,12 +17,12 @@ import flutter_secure_storage_macos
import local_auth_darwin
import package_info_plus
import path_provider_foundation
import screen_retriever
import screen_retriever_macos
import sentry_flutter
import share_plus
import shared_preferences_foundation
import sodium_libs
import sqflite
import sqflite_darwin
import sqlite3_flutter_libs
import tray_manager
import url_launcher_macos
@@ -31,15 +32,16 @@ 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"))
FLALocalAuthPlugin.register(with: registry.registrar(forPlugin: "FLALocalAuthPlugin"))
LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin"))
ScreenRetrieverMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverMacosPlugin"))
SentryFlutterPlugin.register(with: registry.registrar(forPlugin: "SentryFlutterPlugin"))
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))

View File

@@ -2,13 +2,14 @@ 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):
@@ -18,7 +19,7 @@ PODS:
- FlutterMacOS
- flutter_local_notifications (0.0.1):
- FlutterMacOS
- flutter_secure_storage_macos (6.1.1):
- flutter_secure_storage_macos (6.1.3):
- FlutterMacOS
- FlutterMacOS (1.0.0)
- local_auth_darwin (0.0.1):
@@ -32,7 +33,7 @@ PODS:
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- screen_retriever (0.0.1):
- screen_retriever_macos (0.0.1):
- FlutterMacOS
- Sentry/HybridSDK (8.46.0)
- sentry_flutter (8.14.2):
@@ -46,39 +47,44 @@ PODS:
- FlutterMacOS
- sodium_libs (2.2.1):
- FlutterMacOS
- sqflite (0.0.3):
- sqflite_darwin (0.0.4):
- Flutter
- FlutterMacOS
- "sqlite3 (3.46.1+1)":
- "sqlite3/common (= 3.46.1+1)"
- "sqlite3/common (3.46.1+1)"
- "sqlite3/dbstatvtab (3.46.1+1)":
- sqlite3 (3.50.1):
- sqlite3/common (= 3.50.1)
- sqlite3/common (3.50.1)
- sqlite3/dbstatvtab (3.50.1):
- sqlite3/common
- "sqlite3/fts5 (3.46.1+1)":
- sqlite3/fts5 (3.50.1):
- sqlite3/common
- "sqlite3/perf-threadsafe (3.46.1+1)":
- sqlite3/math (3.50.1):
- sqlite3/common
- "sqlite3/rtree (3.46.1+1)":
- sqlite3/perf-threadsafe (3.50.1):
- sqlite3/common
- sqlite3/rtree (3.50.1):
- sqlite3/common
- sqlite3_flutter_libs (0.0.1):
- Flutter
- FlutterMacOS
- "sqlite3 (~> 3.46.0+1)"
- sqlite3 (~> 3.50.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.2.0):
- window_manager (0.5.0):
- FlutterMacOS
DEPENDENCIES:
- app_links (from `Flutter/ephemeral/.symlinks/plugins/app_links/macos`)
- connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/darwin`)
- connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`)
- 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`)
@@ -89,13 +95,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 (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos`)
- screen_retriever_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/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 (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`)
- sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`)
- sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`)
- sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin`)
- 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`)
@@ -110,11 +116,13 @@ EXTERNAL SOURCES:
app_links:
:path: Flutter/ephemeral/.symlinks/plugins/app_links/macos
connectivity_plus:
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/darwin
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos
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:
@@ -135,8 +143,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:
:path: Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos
screen_retriever_macos:
:path: Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos
sentry_flutter:
:path: Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos
share_plus:
@@ -145,10 +153,10 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
sodium_libs:
:path: Flutter/ephemeral/.symlinks/plugins/sodium_libs/macos
sqflite:
:path: Flutter/ephemeral/.symlinks/plugins/sqflite/darwin
sqflite_darwin:
:path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin
sqlite3_flutter_libs:
:path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos
:path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin
tray_manager:
:path: Flutter/ephemeral/.symlinks/plugins/tray_manager/macos
url_launcher_macos:
@@ -157,33 +165,34 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos
SPEC CHECKSUMS:
app_links: 9028728e32c83a0831d9db8cf91c526d16cc5468
connectivity_plus: 3f6c9057f4cd64198dc826edfb0542892f825343
app_links: afe860c55c7ef176cea7fb630a2b7d7736de591d
connectivity_plus: 4adf20a405e25b42b9c9f87feff8f4b6fde18a4e
cupertino_http: 94ac07f5ff090b8effa6c5e2c47871d48ab7c86c
device_info_plus: b0fafc687fb901e2af612763340f1b0d4352f8e5
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
file_saver: e35bd97de451dde55ff8c38862ed7ad0f3418d0f
flutter_inappwebview_macos: c2d68649f9f8f1831bfcd98d73fd6256366d9d1d
flutter_local_authentication: 2f9a2682f498abcc12d7e9729b5007a947170fdc
flutter_local_notifications: 453432cd6399a07d072885bc7828fb2307868856
flutter_secure_storage_macos: b2d62a774c23b060f0b99d0173b0b36abb4a8632
flutter_local_notifications: 13862b132e32eb858dea558a86d45d08daeacfe7
flutter_secure_storage_macos: 7f45e30f838cf2659862a4e4e3ee1c347c2b3b54
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
local_auth_darwin: 553ce4f9b16d3fdfeafce9cf042e7c9f77c1c391
local_auth_darwin: d2e8c53ef0c4f43c646462e3415432c4dab3ae19
objective_c: ec13431e45ba099cb734eb2829a5c1cd37986cba
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
package_info_plus: a8a591e70e87ce97ce5d21b2594f69cea9e0312f
package_info_plus: f0052d280d17aa382b932f399edf32507174e870
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
screen_retriever: 4f97c103641aab8ce183fa5af3b87029df167936
screen_retriever_macos: 452e51764a9e1cdb74b3c541238795849f21557f
Sentry: da60d980b197a46db0b35ea12cb8f39af48d8854
sentry_flutter: 27892878729f42701297c628eb90e7c6529f3684
share_plus: 11c7b7fa7020465584eca3ff6392c5bc1e399d6e
share_plus: 510bf0af1a42cd602274b4629920c9649c52f4cc
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
sodium_libs: b9459e5bfc1185349f43472e79fc5d8e526b2bda
sqflite: c35dad70033b8862124f8337cc994a809fcd9fa3
sqlite3: 0bb0e6389d824e40296f531b858a2a0b71c0d2fb
sqlite3_flutter_libs: 03311aede9d32fb2d24e32bebb8cd01c3b2e6239
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
sqlite3: 1d85290c3321153511f6e900ede7a1608718bbd5
sqlite3_flutter_libs: e7fc8c9ea2200ff3271f08f127842131746b70e2
tray_manager: a104b5c81b578d83f3c3d0f40a997c8b10810166
url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673
window_manager: 1d01fa7ac65a6e6f83b965471b1a7fdd3f06166c
window_manager: b729e31d38fb04905235df9ea896128991cad99e
PODFILE CHECKSUM: 6ff827273ace187339fc5d3684072a26ad85c298

View File

@@ -48,6 +48,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

File diff suppressed because it is too large Load Diff

View File

@@ -10,11 +10,11 @@ environment:
dependencies:
adaptive_theme: ^3.1.0 # done
app_links: ^6.3.3
archive: ^3.3.7
archive: ^4.0.7
auto_size_text: ^3.0.0
base32: ^2.1.3
bip39: ^1.0.6 #done
bloc: ^8.1.2
bloc: ^9.0.0
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: ^2.0.0+2
dotted_border: ^3.1.0
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.5.3
file_picker: ^8.1.7
figma_squircle: ^0.6.3
file_picker: ^10.2.0
# https://github.com/incrediblezayed/file_saver/issues/86
file_saver: ^0.2.11
file_saver: ^0.3.0
fixnum: ^1.1.0
fk_user_agent: ^2.1.0
flutter:
sdk: flutter
flutter_animate: ^4.1.0
flutter_bloc: ^8.0.1
flutter_bloc: ^9.1.1
flutter_context_menu: ^0.2.0
flutter_displaymode: ^0.6.0
flutter_email_sender: ^6.0.2
flutter_email_sender: ^7.0.0
# 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: ^17.2.2
flutter_local_notifications: ^18.0.1
flutter_localizations:
sdk: flutter
flutter_native_splash: ^2.2.13
@@ -87,30 +87,27 @@ dependencies:
pinput: ^5.0.0
pointycastle: ^3.7.3
privacy_screen: ^0.0.6
protobuf: ^3.0.0
protobuf: ^4.1.0
qr_code_scanner: ^1.0.1
qr_flutter: ^4.1.0
sentry: ^8.14.2
sentry_flutter: ^8.14.2
share_plus: ^10.0.2
share_plus: ^11.0.0
shared_preferences: ^2.0.5
sqflite:
git:
url: https://github.com/tekartik/sqflite
path: sqflite
sqflite: ^2.4.2
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.2.1
tray_manager: ^0.5.0
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.4.2
window_manager: ^0.5.0
xdg_directories: ^1.0.4
dev_dependencies:
@@ -118,7 +115,7 @@ dev_dependencies:
flutter_test:
sdk: flutter
json_serializable: ^6.2.0
lints: ^5.0.0
lints: ^5.1.1
mocktail: ^1.0.3
# The following section is specific to Flutter.

View File

@@ -1,4 +1,4 @@
import "package:ente_auth/l10n/l10n.dart";
import "package:ente_auth/l10n/arb/app_localizations.dart";
import "package:flutter/material.dart";
import "package:flutter_localizations/flutter_localizations.dart";
import "package:flutter_test/flutter_test.dart";
@@ -8,7 +8,6 @@ extension PumpApp on WidgetTester {
return pumpWidget(
MaterialApp(
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
],
supportedLocales: AppLocalizations.supportedLocales,

View File

@@ -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/screen_retriever_plugin.h>
#include <screen_retriever_windows/screen_retriever_windows_plugin_c_api.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"));
ScreenRetrieverPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("ScreenRetrieverPlugin"));
ScreenRetrieverWindowsPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("ScreenRetrieverWindowsPluginCApi"));
SentryFlutterPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SentryFlutterPlugin"));
SharePlusWindowsPluginCApiRegisterWithRegistrar(

View File

@@ -10,7 +10,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
flutter_local_authentication
flutter_secure_storage_windows
local_auth_windows
screen_retriever
screen_retriever_windows
sentry_flutter
share_plus
sodium_libs

View File

@@ -0,0 +1,3 @@
{
"flutter": "3.29.3"
}

View File

@@ -43,3 +43,6 @@ fastlane/report.xml
# Android related
android/app/build/
# FVM Version Cache
.fvm/

View File

@@ -46,7 +46,7 @@ You can alternatively install the build from PlayStore or F-Droid.
## 🧑‍💻 Building from source
1. [Install Flutter v3.24.3](https://flutter.dev/docs/get-started/install).
1. [Install Flutter v3.29.3](https://flutter.dev/docs/get-started/install).
2. Pull in all submodules with `git submodule update --init --recursive`

View File

@@ -34,6 +34,7 @@ android {
ndkVersion = flutter.ndkVersion
compileOptions {
coreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
@@ -132,7 +133,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'
@@ -142,7 +143,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") {

View File

@@ -1,11 +1,5 @@
package io.ente.photos
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity : FlutterFragmentActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine)
}
}
class MainActivity : FlutterFragmentActivity() {}

View File

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

View File

@@ -18,7 +18,7 @@ pluginManagement {
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.1.0" apply false
id "com.android.application" version "8.6.0" apply false
id "org.jetbrains.kotlin.android" version "2.1.10" apply false
}

View File

@@ -32,3 +32,5 @@ Flutter/.last_build_id
!default.mode2v3
!default.pbxuser
!default.perspectivev3
Flutter/ephemeral

View File

@@ -1,7 +1,6 @@
# Uncomment this line to define a global platform for your project
source 'https://github.com/ente-io/ffmpeg-kit-custom-repo-ios.git'
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.

View File

@@ -18,37 +18,37 @@ PODS:
- Flutter
- file_saver (0.0.1):
- Flutter
- Firebase/CoreOnly (11.8.0):
- FirebaseCore (~> 11.8.0)
- Firebase/Messaging (11.8.0):
- Firebase/CoreOnly (11.15.0):
- FirebaseCore (~> 11.15.0)
- Firebase/Messaging (11.15.0):
- Firebase/CoreOnly
- FirebaseMessaging (~> 11.8.0)
- firebase_core (3.12.0):
- Firebase/CoreOnly (= 11.8.0)
- FirebaseMessaging (~> 11.15.0)
- firebase_core (3.15.1):
- Firebase/CoreOnly (= 11.15.0)
- Flutter
- firebase_messaging (15.2.3):
- Firebase/Messaging (= 11.8.0)
- firebase_messaging (15.2.9):
- Firebase/Messaging (= 11.15.0)
- firebase_core
- Flutter
- 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)
- 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)
- PromisesObjC (~> 2.4)
- FirebaseMessaging (11.8.0):
- FirebaseCore (~> 11.8.0)
- FirebaseMessaging (11.15.0):
- FirebaseCore (~> 11.15.0)
- FirebaseInstallations (~> 11.0)
- GoogleDataTransport (~> 10.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
- GoogleUtilities/Environment (~> 8.0)
- GoogleUtilities/Reachability (~> 8.0)
- GoogleUtilities/UserDefaults (~> 8.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
- GoogleUtilities/Environment (~> 8.1)
- GoogleUtilities/Reachability (~> 8.1)
- GoogleUtilities/UserDefaults (~> 8.1)
- nanopb (~> 3.30910.0)
- Flutter (1.0.0)
- flutter_email_sender (0.0.1):
@@ -127,9 +127,6 @@ 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):
@@ -176,7 +173,7 @@ PODS:
- FlutterMacOS
- permission_handler_apple (9.3.0):
- Flutter
- photo_manager (2.0.0):
- photo_manager (3.7.1):
- Flutter
- FlutterMacOS
- privacy_screen (0.0.1):
@@ -203,23 +200,26 @@ PODS:
- sqflite_darwin (0.0.4):
- Flutter
- FlutterMacOS
- sqlite3 (3.49.2):
- sqlite3/common (= 3.49.2)
- sqlite3/common (3.49.2)
- sqlite3/dbstatvtab (3.49.2):
- sqlite3 (3.50.1):
- sqlite3/common (= 3.50.1)
- sqlite3/common (3.50.1)
- sqlite3/dbstatvtab (3.50.1):
- sqlite3/common
- sqlite3/fts5 (3.49.2):
- sqlite3/fts5 (3.50.1):
- sqlite3/common
- sqlite3/perf-threadsafe (3.49.2):
- sqlite3/math (3.50.1):
- sqlite3/common
- sqlite3/rtree (3.49.2):
- sqlite3/perf-threadsafe (3.50.1):
- sqlite3/common
- sqlite3/rtree (3.50.1):
- sqlite3/common
- sqlite3_flutter_libs (0.0.1):
- Flutter
- FlutterMacOS
- sqlite3 (~> 3.49.0)
- sqlite3 (~> 3.50.1)
- sqlite3/dbstatvtab
- sqlite3/fts5
- sqlite3/math
- sqlite3/perf-threadsafe
- sqlite3/rtree
- system_info_plus (0.0.1):
@@ -269,7 +269,6 @@ 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`)
@@ -304,7 +303,7 @@ DEPENDENCIES:
- workmanager (from `.symlinks/plugins/workmanager/ios`)
SPEC REPOS:
https://github.com/ente-io/ffmpeg-kit-custom-repo-ios.git:
https://github.com/ente-io/ffmpeg-kit-custom-repo-ios:
- ffmpeg_kit_custom
trunk:
- Firebase
@@ -377,8 +376,6 @@ 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:
@@ -445,84 +442,83 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/workmanager/ios"
SPEC CHECKSUMS:
app_links: f3e17e4ee5e357b39d8b95290a9b2c299fca71c6
battery_info: b6c551049266af31556b93c9d9b9452cfec0219f
connectivity_plus: 2a701ffec2c0ae28a48cf7540e279787e77c447d
cupertino_http: 947a233f40cfea55167a49f2facc18434ea117ba
dart_ui_isolate: d5bcda83ca4b04f129d70eb90110b7a567aece14
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
app_links: 76b66b60cc809390ca1ad69bfd66b998d2387ac7
battery_info: 83f3aae7be2fccefab1d2bf06b8aa96f11c8bcdd
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
cupertino_http: 94ac07f5ff090b8effa6c5e2c47871d48ab7c86c
dart_ui_isolate: 46f6714abe6891313267153ef6f9748d8ecfcab1
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
ffmpeg_kit_custom: 682b4f2f1ff1f8abae5a92f6c3540f2441d5be99
ffmpeg_kit_flutter: 9dce4803991478c78c6fb9f972703301101095fe
file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808
Firebase: d80354ed7f6df5f9aca55e9eb47cc4b634735eaf
firebase_core: 6e223dfa350b2edceb729cea505eaaef59330682
firebase_messaging: 07fde77ae28c08616a1d4d870450efc2b38cf40d
FirebaseCore: 99fe0c4b44a39f37d99e6404e02009d2db5d718d
FirebaseCoreInternal: df24ce5af28864660ecbd13596fc8dd3a8c34629
FirebaseInstallations: 6c963bd2a86aca0481eef4f48f5a4df783ae5917
FirebaseMessaging: 487b634ccdf6f7b7ff180fdcb2a9935490f764e8
ffmpeg_kit_flutter: 915b345acc97d4142e8a9a8549d177ff10f043f5
file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6
Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e
firebase_core: ece862f94b2bc72ee0edbeec7ab5c7cb09fe1ab5
firebase_messaging: e1a5fae495603115be1d0183bc849da748734e2b
FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e
FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4
FirebaseInstallations: 317270fec08a5d418fdbc8429282238cab3ac843
FirebaseMessaging: 3b26e2cee503815e01c3701236b020aa9b576f09
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
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
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
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
home_widget: 0434835a4c9a75704264feff6be17ea40e0f0d57
image_editor_common: d6f6644ae4a6de80481e89fe6d0a8c49e30b4b43
in_app_purchase_storekit: a1ce04056e23eecc666b086040239da7619cd783
integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573
launcher_icon_switcher: 8e0ad2131a20c51c1dd939896ee32e70cd845b37
home_widget: f169fc41fd807b4d46ab6615dc44d62adbf9f64f
image_editor_common: 3de87e7c4804f4ae24c8f8a998362b98c105cac1
in_app_purchase_storekit: d1a48cb0f8b29dbf5f85f782f5dd79b21b90a5e6
integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e
launcher_icon_switcher: 84c218d233505aa7d8655d8fa61a3ba802c022da
libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3
local_auth_ios: 5046a18c018dd973247a0564496c8898dbb5adf9
local_auth_ios: f7a1841beef3151d140a967c2e46f30637cdf451
Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d
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
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
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
native_video_player: 29ab24a926804ac8c4a57eb6d744c7d927c2bc3e
objective_c: 77e887b5ba1827970907e10e832eec1683f3431d
onnxruntime: e7c2ae44385191eaad5ae64c935a72debaddc997
native_video_player: 6809dec117e8997161dbfb42a6f90d6df71a504d
objective_c: 89e720c30d716b036faf9c9684022048eee1eee2
onnxruntime: f9b296392c96c42882be020a59dbeac6310d81b2
onnxruntime-c: a909204639a1f035f575127ac406f781ac797c9c
onnxruntime-objc: b6fab0f1787aa6f7190c2013f03037df4718bd8b
open_mail_app: 70273c53f768beefdafbe310c3d9086e4da3cb02
open_mail_app: 7314a609e88eed22d53671279e189af7a0ab0f11
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
photo_manager: ff695c7a1dd5bc379974953a2b5c0a293f7c4c8a
privacy_screen: 1a131c052ceb3c3659934b003b0d397c2381a24e
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
photo_manager: 1d80ae07a89a67dfbcae95953a1e5a24af7c3e62
privacy_screen: 3159a541f5d3a31bea916cfd4e58f9dc722b3fd4
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
receive_sharing_intent: 79c848f5b045674ad60b9fea3bafea59962ad2c1
receive_sharing_intent: 222384f00ffe7e952bbfabaa9e3967cb87e5fe00
SDWebImage: f29024626962457f3470184232766516dee8dfea
SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
Sentry: da60d980b197a46db0b35ea12cb8f39af48d8854
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
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
PODFILE CHECKSUM: a8ef88ad74ba499756207e7592c6071a96756d18
PODFILE CHECKSUM: cce2cd3351d3488dca65b151118552b680e23635
COCOAPODS: 1.16.2

View File

@@ -548,7 +548,6 @@
"${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",
@@ -644,7 +643,6 @@
"${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",

View File

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

View File

@@ -1,3 +0,0 @@
arb-dir: lib/l10n
template-arb-file: intl_en.arb
output-localization-file: app_localizations.dart

View File

@@ -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_gen/gen_l10n/app_localizations.dart';
import "package:flutter_localizations/flutter_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,6 +20,7 @@ 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";
@@ -74,8 +75,10 @@ class _EnteAppState extends State<EnteApp> with WidgetsBindingObserver {
_peopleChangedSubscription = Bus.instance.on<PeopleChangedEvent>().listen(
(event) async {
_changeCallbackDebouncer.run(
() async =>
unawaited(PeopleHomeWidgetService.instance.checkPeopleChanged()),
() async {
unawaited(PeopleHomeWidgetService.instance.checkPeopleChanged());
unawaited(SmartAlbumsService.instance.syncSmartAlbums());
},
);
},
);
@@ -143,8 +146,10 @@ class _EnteAppState extends State<EnteApp> with WidgetsBindingObserver {
supportedLocales: appSupportedLocales,
localeListResolutionCallback: localResolutionCallBack,
localizationsDelegates: const [
...AppLocalizations.localizationsDelegates,
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
),
),
@@ -166,8 +171,10 @@ class _EnteAppState extends State<EnteApp> with WidgetsBindingObserver {
supportedLocales: appSupportedLocales,
localeListResolutionCallback: localResolutionCallBack,
localizationsDelegates: const [
...AppLocalizations.localizationsDelegates,
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
),
);

View File

@@ -1,5 +1,3 @@
library super_logging;
import 'dart:async';
import 'dart:collection';
import 'dart:core';

View File

@@ -128,4 +128,21 @@ 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),
),
);
}
}

View File

@@ -1479,6 +1479,7 @@ 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',
);

View File

@@ -359,6 +359,10 @@ class MLDataDB with SqlDbBase implements IMLDataDB<int> {
}
}
return mapRowToFace(faceMaps.first);
} else if (clusterID == null) {
_logger.severe(
"Didn't find any faces for personID $personID in `getCoverFaceForPerson`. fileID: $fileId, clusterIDs: $clusterIDs",
);
}
}
if (clusterID != null) {
@@ -380,11 +384,19 @@ class MLDataDB with SqlDbBase implements IMLDataDB<int> {
return face;
}
}
} else {
_logger.severe(
"Didn't find any faces for clusterID $clusterID in `getCoverFaceForPerson`. faces: $faces",
);
}
}
if (personID == null && clusterID == null) {
_logger.severe("personID and clusterID cannot be null both");
throw Exception("personID and clusterID cannot be null");
}
_logger.severe(
"Something went wrong finding a face from `getCoverFaceForPerson` (personID: $personID, clusterID: $clusterID)",
);
return null;
}

View File

@@ -42,20 +42,22 @@ final lightThemeData = ThemeData(
bodyLarge: const TextStyle(color: Colors.orange),
),
cardColor: const Color.fromRGBO(250, 250, 250, 1.0),
dialogTheme: const DialogTheme().copyWith(
backgroundColor: const Color.fromRGBO(250, 250, 250, 1.0), //
titleTextStyle: const TextStyle(
dialogTheme: const DialogThemeData(
backgroundColor: Color.fromRGBO(250, 250, 250, 1.0), //
titleTextStyle: TextStyle(
color: Colors.black,
fontSize: 24,
fontWeight: FontWeight.w600,
),
contentTextStyle: const TextStyle(
contentTextStyle: TextStyle(
fontFamily: 'Inter-Medium',
color: Colors.black,
fontSize: 16,
fontWeight: FontWeight.w500,
),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
),
),
inputDecorationTheme: const InputDecorationTheme().copyWith(
focusedBorder: const UnderlineInputBorder(
@@ -117,20 +119,22 @@ final darkThemeData = ThemeData(
elevation: 0,
),
cardColor: const Color.fromRGBO(10, 15, 15, 1.0),
dialogTheme: const DialogTheme().copyWith(
backgroundColor: const Color.fromRGBO(15, 15, 15, 1.0),
titleTextStyle: const TextStyle(
dialogTheme: const DialogThemeData(
backgroundColor: Color.fromRGBO(15, 15, 15, 1.0),
titleTextStyle: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.w600,
),
contentTextStyle: const TextStyle(
contentTextStyle: TextStyle(
fontFamily: 'Inter-Medium',
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w500,
),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
),
),
inputDecorationTheme: const InputDecorationTheme().copyWith(
focusedBorder: const UnderlineInputBorder(
@@ -206,7 +210,7 @@ TextTheme _buildTextTheme(Color textColor) {
fontWeight: FontWeight.w500,
),
bodySmall: TextStyle(
color: textColor.withOpacity(0.6),
color: textColor.withValues(alpha: 0.6),
fontSize: 14,
fontWeight: FontWeight.w500,
),
@@ -278,7 +282,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).withOpacity(0.75)
? const Color.fromRGBO(0, 0, 0, 1).withValues(alpha: 0.75)
: const Color.fromRGBO(255, 255, 255, 1);
Color get bgColorForQuestions => brightness == Brightness.light
@@ -289,7 +293,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).withOpacity(0.1);
: const Color.fromRGBO(255, 255, 255, 1).withValues(alpha: 0.1);
Color get stepProgressUnselectedColor => brightness == Brightness.light
? const Color.fromRGBO(196, 196, 196, 0.6)
@@ -300,20 +304,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).withOpacity(0.8)
: const Color.fromRGBO(255, 255, 255, 1).withOpacity(0.5);
? const Color.fromRGBO(0, 0, 0, 1).withValues(alpha: 0.8)
: const Color.fromRGBO(255, 255, 255, 1).withValues(alpha: 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).withOpacity(0.5)
: const Color.fromRGBO(255, 255, 255, 1).withOpacity(0.5);
? const Color.fromRGBO(0, 0, 0, 1).withValues(alpha: 0.5)
: const Color.fromRGBO(255, 255, 255, 1).withValues(alpha: 0.5);
Color get dotsIndicatorInactiveColor => brightness == Brightness.light
? const Color.fromRGBO(0, 0, 0, 1).withOpacity(0.12)
: const Color.fromRGBO(255, 255, 255, 1).withOpacity(0.12);
? const Color.fromRGBO(0, 0, 0, 1).withValues(alpha: 0.12)
: const Color.fromRGBO(255, 255, 255, 1).withValues(alpha: 0.12);
Color get toastTextColor => brightness == Brightness.light
? const Color.fromRGBO(255, 255, 255, 1)
@@ -336,8 +340,8 @@ extension CustomColorScheme on ColorScheme {
: const Color.fromRGBO(150, 150, 150, 1);
Color get searchResultsBackgroundColor => brightness == Brightness.light
? Colors.black.withOpacity(0.32)
: Colors.black.withOpacity(0.64);
? Colors.black.withValues(alpha: 0.32)
: Colors.black.withValues(alpha: 0.64);
EnteTheme get enteTheme =>
brightness == Brightness.light ? lightTheme : darkTheme;

View File

@@ -57,9 +57,10 @@ const kLastFGTaskHeartBeatTime = "fg_task_hb_time";
const kHeartBeatFrequency = Duration(seconds: 1);
const kFGSyncFrequency = Duration(minutes: 5);
const kFGHomeWidgetSyncFrequency = Duration(minutes: 15);
const kBGTaskTimeout = Duration(seconds: 28);
const kBGTaskTimeout = Duration(seconds: 58);
const kBGPushTimeout = Duration(seconds: 28);
const kFGTaskDeathTimeoutInMicroseconds = 5000000;
bool isProcessBg = true;
void main() async {
debugRepaintRainbowEnabled = false;
@@ -86,6 +87,7 @@ void main() async {
Future<void> _runInForeground(AdaptiveThemeMode? savedThemeMode) async {
return await runWithLogs(() async {
_logger.info("Starting app in foreground");
isProcessBg = false;
await _init(false, via: 'mainMethod');
final Locale? locale = await getLocale(noFallback: true);
runApp(
@@ -306,7 +308,7 @@ void logLocalSettings() {
);
_logger.info("Gallery grid size: ${localSettings.getPhotoGridSize()}");
_logger.info(
"Video streaming is enalbed: ${VideoPreviewService.instance.isVideoStreamingEnabled}",
"Video streaming is enabled: ${VideoPreviewService.instance.isVideoStreamingEnabled}",
);
}

View File

@@ -5,6 +5,7 @@ enum EntityType {
person,
cgroup,
unknown,
smartConfig,
}
EntityType typeFromString(String type) {
@@ -15,6 +16,8 @@ EntityType typeFromString(String type) {
return EntityType.location;
case "cgroup":
return EntityType.cgroup;
case "sconfig":
return EntityType.cgroup;
}
debugPrint("unexpected entity type $type");
return EntityType.unknown;
@@ -22,10 +25,13 @@ EntityType typeFromString(String type) {
extension EntityTypeExtn on EntityType {
bool isZipped() {
if (this == EntityType.location || this == EntityType.person) {
return false;
switch (this) {
case EntityType.location:
case EntityType.person:
return false;
default:
return true;
}
return true;
}
String typeToString() {
@@ -36,6 +42,8 @@ extension EntityTypeExtn on EntityType {
return "person";
case EntityType.cgroup:
return "cgroup";
case EntityType.smartConfig:
return "sconfig";
case EntityType.unknown:
return "unknown";
}

View File

@@ -0,0 +1,143 @@
typedef PersonInfo = ({int updatedAt, Set<int> addedFiles});
class SmartAlbumConfig {
// A nullable remote ID for syncing purposes
final String? remoteId;
final int collectionId;
// person ids
final Set<String> personIDs;
// person id mapped with updatedat, file ids
final Map<String, PersonInfo> infoMap;
final int updatedAt;
SmartAlbumConfig({
this.remoteId,
required this.collectionId,
required this.personIDs,
required this.infoMap,
this.updatedAt = 0,
});
Future<SmartAlbumConfig> getUpdatedConfig(Set<String> newPersonsIds) async {
final toAdd = newPersonsIds.difference(personIDs);
final toRemove = personIDs.difference(newPersonsIds);
final newInfoMap = Map<String, PersonInfo>.from(infoMap);
// Remove whats not needed
for (final personId in toRemove) {
newInfoMap.remove(personId);
}
// Add files which are needed
for (final personId in toAdd) {
newInfoMap[personId] = (updatedAt: 0, addedFiles: <int>{});
}
return SmartAlbumConfig(
remoteId: remoteId,
collectionId: collectionId,
personIDs: newPersonsIds,
infoMap: newInfoMap,
updatedAt: DateTime.now().millisecondsSinceEpoch,
);
}
Future<SmartAlbumConfig> addFiles(
String personId,
int updatedAt,
Set<int> fileId,
) async {
if (!infoMap.containsKey(personId)) {
return this;
}
final newInfoMap = Map<String, PersonInfo>.from(infoMap);
newInfoMap[personId] = (
updatedAt: updatedAt,
addedFiles: newInfoMap[personId]!.addedFiles.union(fileId),
);
return SmartAlbumConfig(
remoteId: remoteId,
collectionId: collectionId,
personIDs: personIDs,
infoMap: newInfoMap,
updatedAt: DateTime.now().millisecondsSinceEpoch,
);
}
// toJson and fromJson methods
Map<String, dynamic> toJson() {
return {
"remote_id": remoteId,
"collection_id": collectionId,
"person_ids": personIDs.toList(),
"updated_at": updatedAt,
"info_map": infoMap.map(
(key, value) => MapEntry(
key,
{
"updated_at": value.updatedAt,
"added_files": value.addedFiles.toList(),
},
),
),
};
}
factory SmartAlbumConfig.fromJson(
Map<String, dynamic> json,
String? remoteId,
int? updatedAt,
) {
final personIDs = Set<String>.from(json["person_ids"] as List? ?? []);
final infoMap = (json["info_map"] as Map<String, dynamic>).map(
(key, value) => MapEntry(
key,
(
updatedAt: value["updated_at"] as int? ??
DateTime.now().millisecondsSinceEpoch,
addedFiles: Set<int>.from(value["added_files"] as List? ?? []),
),
),
);
return SmartAlbumConfig(
remoteId: remoteId,
collectionId: json["collection_id"] as int,
personIDs: personIDs,
infoMap: infoMap,
updatedAt: updatedAt ?? DateTime.now().millisecondsSinceEpoch,
);
}
SmartAlbumConfig merge(SmartAlbumConfig b) {
if (remoteId == b.remoteId) {
if (updatedAt >= b.updatedAt) {
return this;
}
return b;
}
return SmartAlbumConfig(
remoteId: b.updatedAt <= updatedAt ? b.remoteId : remoteId,
collectionId: b.collectionId,
personIDs: personIDs.union(b.personIDs),
infoMap: {
...infoMap,
...b.infoMap.map(
(key, value) => MapEntry(
key,
(
updatedAt: infoMap[key]?.updatedAt != null &&
infoMap[key]!.updatedAt > value.updatedAt
? infoMap[key]!.updatedAt
: value.updatedAt,
addedFiles: infoMap[key]?.addedFiles.union(value.addedFiles) ??
value.addedFiles,
),
),
),
},
);
}
}

View File

@@ -167,7 +167,7 @@ class DownloadManager {
final existingSize = await baseFile.length();
if (existingSize == task.totalBytes) {
_logger.info(
'Download already exists for ${task.filename} (${existingSize}/${task.totalBytes} bytes)',
'Download already exists for ${task.filename} ($existingSize/${task.totalBytes} bytes)',
);
task = task.copyWith(
status: DownloadStatus.completed,

View File

@@ -79,16 +79,19 @@ class EntityService {
" ${id == null ? 'Adding' : 'Updating'} entity of type: " +
type.typeToString(),
);
late LocalEntityData localData;
final EntityData data = id == null
? await _gateway.createEntity(type, encryptedData, header)
: await _gateway.updateEntity(type, id, encryptedData, header);
final LocalEntityData localData = LocalEntityData(
localData = LocalEntityData(
id: data.id,
type: type,
data: plainText,
ownerID: data.userID,
updatedAt: data.updatedAt,
);
await _db.upsertEntities([localData]);
syncEntities().ignore();
return localData;
@@ -103,6 +106,8 @@ class EntityService {
try {
await _remoteToLocalSync(EntityType.location);
await _remoteToLocalSync(EntityType.cgroup);
// TODO: Change to smart config
await _remoteToLocalSync(EntityType.person);
} catch (e) {
_logger.severe("Failed to sync entities", e);
}
@@ -249,4 +254,11 @@ class EntityService {
final hash = md5.convert(utf8.encode(preHash)).toString().substring(0, 10);
return hash;
}
Future<Map<String, int>> getUpdatedAts(
EntityType type,
List<String> personIds,
) async {
return await _db.getUpdatedAts(type, personIds);
}
}

View File

@@ -0,0 +1,49 @@
import "dart:async";
import "dart:isolate";
import "package:ffmpeg_kit_flutter/ffmpeg_kit.dart";
import "package:ffmpeg_kit_flutter/ffprobe_kit.dart";
import "package:flutter/services.dart";
import "package:photos/utils/ffprobe_util.dart";
class IsolatedFfmpegService {
static Future<Map> runFfmpeg(String command) async {
final rootIsolateToken = RootIsolateToken.instance!;
return await Isolate.run<Map>(() => _ffmpegRun(command, rootIsolateToken));
}
static Future<Map> getVideoInfo(String file) async {
final rootIsolateToken = RootIsolateToken.instance!;
return await Isolate.run<Map>(() => _getVideoProps(file, rootIsolateToken));
}
}
@pragma('vm:entry-point')
Future<Map> _getVideoProps(
String filePath,
RootIsolateToken rootIsolateToken,
) async {
BackgroundIsolateBinaryMessenger.ensureInitialized(rootIsolateToken);
final session = await FFprobeKit.getMediaInformation(filePath);
final mediaInfo = session.getMediaInformation();
if (mediaInfo == null) {
return {};
}
final metadata = await FFProbeUtil.getMetadata(mediaInfo);
return metadata;
}
@pragma('vm:entry-point')
Future<Map> _ffmpegRun(String value, RootIsolateToken rootIsolateToken) async {
BackgroundIsolateBinaryMessenger.ensureInitialized(rootIsolateToken);
final session = await FFmpegKit.execute(value, true);
final returnCode = await session.getReturnCode();
final output = await session.getOutput();
return {
"returnCode": returnCode?.getValue(),
"output": output,
};
}

View File

@@ -1,15 +1,12 @@
import 'dart:async';
import 'dart:typed_data' show Uint8List;
import "package:computer/computer.dart";
import "package:logging/logging.dart";
import "package:photos/models/ml/face/box.dart";
import "package:photos/services/isolate_functions.dart";
import "package:photos/services/isolate_service.dart";
import "package:photos/utils/image_ml_util.dart";
final Computer _computer = Computer.shared();
class FaceThumbnailGenerator extends SuperIsolate {
@override
Logger get logger => _logger;
@@ -37,20 +34,29 @@ class FaceThumbnailGenerator extends SuperIsolate {
String imagePath,
List<FaceBox> faceBoxes,
) async {
final List<Map<String, dynamic>> faceBoxesJson =
faceBoxes.map((box) => box.toJson()).toList();
final List<Uint8List> faces = await runInIsolate(
IsolateOperation.generateFaceThumbnails,
{
'imagePath': imagePath,
'faceBoxesList': faceBoxesJson,
},
).then((value) => value.cast<Uint8List>());
final compressedFaces =
await compressFaceThumbnails({'listPngBytes': faces});
_logger.fine(
"Compressed face thumbnails from sizes ${faces.map((e) => e.length / 1024).toList()} to ${compressedFaces.map((e) => e.length / 1024).toList()} kilobytes",
);
return compressedFaces;
try {
_logger.info(
"Generating face thumbnails for ${faceBoxes.length} face boxes in $imagePath",
);
final List<Map<String, dynamic>> faceBoxesJson =
faceBoxes.map((box) => box.toJson()).toList();
final List<Uint8List> faces = await runInIsolate(
IsolateOperation.generateFaceThumbnails,
{
'imagePath': imagePath,
'faceBoxesList': faceBoxesJson,
},
).then((value) => value.cast<Uint8List>());
_logger.info("Generated face thumbnails");
final compressedFaces =
await compressFaceThumbnails({'listPngBytes': faces});
_logger.info(
"Compressed face thumbnails from sizes ${faces.map((e) => e.length / 1024).toList()} to ${compressedFaces.map((e) => e.length / 1024).toList()} kilobytes",
);
return compressedFaces;
} catch (e, s) {
_logger.severe("Failed to generate face thumbnails", e, s);
rethrow;
}
}
}

View File

@@ -3,7 +3,6 @@ import "dart:io" show File;
import "package:flutter/cupertino.dart";
import "package:flutter/foundation.dart" show kDebugMode;
import "package:flutter/material.dart" show BuildContext;
import "package:logging/logging.dart";
import "package:path_provider/path_provider.dart";
import "package:photos/core/event_bus.dart";

View File

@@ -0,0 +1,280 @@
import "dart:async";
import "dart:convert";
import "package:flutter/widgets.dart" show BuildContext;
import "package:logging/logging.dart";
import "package:photos/generated/l10n.dart";
import "package:photos/models/api/entity/type.dart";
import "package:photos/models/collection/smart_album_config.dart";
import "package:photos/models/local_entity_data.dart";
import "package:photos/service_locator.dart" show entityService;
import "package:photos/services/collections_service.dart";
import "package:photos/services/search_service.dart";
import "package:photos/ui/actions/collection/collection_file_actions.dart";
import "package:photos/ui/actions/collection/collection_sharing_actions.dart";
import "package:photos/ui/components/action_sheet_widget.dart"
show showActionSheet;
import "package:photos/ui/components/buttons/button_widget.dart";
import "package:photos/ui/components/models/button_type.dart";
class SmartAlbumsService {
SmartAlbumsService._();
static final SmartAlbumsService instance = SmartAlbumsService._();
final _logger = Logger((SmartAlbumsService).toString());
int _lastCacheRefreshTime = 0;
Future<Map<int, SmartAlbumConfig>>? _cachedConfigsFuture;
static const type = EntityType.person;
void clearCache() {
_cachedConfigsFuture = null;
_lastCacheRefreshTime = 0;
}
Future<void> refreshSmartConfigCache() async {
_lastCacheRefreshTime = 0;
// wait to ensure cache is refreshed
final _ = await getSmartConfigs();
}
int lastRemoteSyncTime() {
return entityService.lastSyncTime(type);
}
Future<Map<int, SmartAlbumConfig>> getSmartConfigs() async {
final lastRemoteSyncTimeValue = lastRemoteSyncTime();
if (_lastCacheRefreshTime != lastRemoteSyncTimeValue) {
_lastCacheRefreshTime = lastRemoteSyncTimeValue;
_cachedConfigsFuture = null; // Invalidate cache
}
_cachedConfigsFuture ??= _fetchAndCacheSConfigs();
return await _cachedConfigsFuture!;
}
Future<Map<int, SmartAlbumConfig>> _fetchAndCacheSConfigs() async {
_logger.finest("reading all smart configs from local db");
final entities = await entityService.getEntities(type);
final result = _decodeSConfigEntities(
{"entity": entities},
);
final sconfigs = result["sconfigs"] as Map<int, SmartAlbumConfig>;
final collectionToUpdate = result["collectionToUpdate"] as Set<int>;
final idToDelete = result["idToDelete"] as Set<String>;
// update the merged config to remote db
for (final collectionid in collectionToUpdate) {
try {
await saveConfig(sconfigs[collectionid]!);
} catch (error, stackTrace) {
_logger.severe(
"Failed to update smart album config for collection $collectionid",
error,
stackTrace,
);
}
}
// delete all remote ids that are merged into the config
for (final remoteId in idToDelete) {
try {
await _deleteEntry(id: remoteId);
} catch (error, stackTrace) {
_logger.severe(
"Failed to delete smart album config for remote id $remoteId",
error,
stackTrace,
);
}
}
return sconfigs;
}
Map<String, dynamic> _decodeSConfigEntities(
Map<String, dynamic> param,
) {
final entities = (param["entity"] as List<LocalEntityData>);
final Map<int, SmartAlbumConfig> sconfigs = {};
final Set<int> collectionToUpdate = {};
final Set<String> idToDelete = {};
for (final entity in entities) {
try {
var config = SmartAlbumConfig.fromJson(
json.decode(entity.data),
entity.id,
entity.updatedAt,
);
if (sconfigs.containsKey(config.collectionId)) {
final existingConfig = sconfigs[config.collectionId]!;
final collectionIdToKeep = config.updatedAt < existingConfig.updatedAt
? config.collectionId
: existingConfig.collectionId;
final remoteIdToDelete = config.updatedAt < existingConfig.updatedAt
? existingConfig.remoteId
: config.remoteId;
config = config.merge(sconfigs[config.collectionId]!);
// Update the config to be updated and deleted list
collectionToUpdate.add(collectionIdToKeep);
idToDelete.add(remoteIdToDelete!);
}
sconfigs[config.collectionId] = config;
} catch (error, stackTrace) {
_logger.severe(
"Failed to decode smart album config",
error,
stackTrace,
);
}
}
return {
"sconfigs": sconfigs,
"collectionToUpdate": collectionToUpdate,
"idToDelete": idToDelete,
};
}
Future<void> syncSmartAlbums() async {
final cachedConfigs = await _fetchAndCacheSConfigs();
for (final entry in cachedConfigs.entries) {
final collectionId = entry.key;
final config = entry.value;
final infoMap = config.infoMap;
// Person Id key mapped to updatedAt value
final updatedAtMap = await entityService.getUpdatedAts(
EntityType.cgroup,
config.personIDs.toList(),
);
for (final personId in config.personIDs) {
// compares current updateAt with last added file's updatedAt
if (updatedAtMap[personId] == null ||
infoMap[personId] == null ||
(updatedAtMap[personId]! <= infoMap[personId]!.updatedAt)) {
continue;
}
final toBeSynced = (await SearchService.instance
.getClusterFilesForPersonID(personId))
.entries
.expand((e) => e.value)
.toList()
..removeWhere(
(e) =>
e.uploadedFileID == null ||
config.infoMap[personId]!.addedFiles.contains(e.uploadedFileID),
);
if (toBeSynced.isNotEmpty) {
final CollectionActions collectionActions =
CollectionActions(CollectionsService.instance);
final result = await collectionActions.addToCollection(
null,
collectionId,
false,
selectedFiles: toBeSynced,
);
if (result) {
final newConfig = await config.addFiles(
personId,
updatedAtMap[personId]!,
toBeSynced.map((e) => e.uploadedFileID!).toSet(),
);
await saveConfig(newConfig);
}
}
}
}
}
Future<void> saveConfig(SmartAlbumConfig config) async {
await _addOrUpdateEntity(
type,
config.toJson(),
id: config.remoteId,
);
}
Future<SmartAlbumConfig?> getConfig(int collectionId) async {
final cachedConfigs = await getSmartConfigs();
return cachedConfigs[collectionId];
}
Future<bool> removeFilesDialog(
BuildContext context,
) async {
final completer = Completer<bool>();
await showActionSheet(
context: context,
body: "Should the files related to the person be removed?",
buttons: [
ButtonWidget(
labelText: S.of(context).yes,
buttonType: ButtonType.neutral,
buttonSize: ButtonSize.large,
shouldStickToDarkTheme: true,
buttonAction: ButtonAction.first,
shouldSurfaceExecutionStates: true,
isInAlert: true,
onTap: () async {
completer.complete(true);
},
),
ButtonWidget(
labelText: S.of(context).no,
buttonType: ButtonType.secondary,
buttonSize: ButtonSize.large,
shouldStickToDarkTheme: true,
buttonAction: ButtonAction.cancel,
isInAlert: true,
onTap: () async {
completer.complete(false);
},
),
],
);
return completer.future;
}
/// Wrapper method for entityService.addOrUpdate that handles cache refresh
Future<LocalEntityData> _addOrUpdateEntity(
EntityType type,
Map<String, dynamic> jsonMap, {
String? id,
}) async {
final result = await entityService.addOrUpdate(
type,
jsonMap,
id: id,
);
_lastCacheRefreshTime = 0; // Invalidate cache
return result;
}
Future<void> _deleteEntry({
required String id,
}) async {
await entityService.deleteEntry(id);
_lastCacheRefreshTime = 0; // Invalidate cache
}
}

View File

@@ -15,6 +15,7 @@ import 'package:photos/events/trigger_logout_event.dart';
import 'package:photos/models/file/file_type.dart';
import "package:photos/services/language_service.dart";
import 'package:photos/services/notification_service.dart';
import "package:photos/services/smart_albums_service.dart";
import 'package:photos/services/sync/local_sync_service.dart';
import 'package:photos/services/sync/remote_sync_service.dart';
import 'package:photos/utils/file_uploader.dart';
@@ -199,6 +200,7 @@ class SyncService {
if (shouldSync) {
await _remoteSyncService.sync();
}
await SmartAlbumsService.instance.syncSmartAlbums();
}
}

View File

@@ -6,8 +6,6 @@ import "dart:io";
import "package:collection/collection.dart";
import "package:dio/dio.dart";
import "package:encrypt/encrypt.dart" as enc;
import "package:ffmpeg_kit_flutter/ffmpeg_kit.dart";
import "package:ffmpeg_kit_flutter/ffmpeg_session.dart";
import "package:ffmpeg_kit_flutter/return_code.dart";
import "package:flutter/foundation.dart";
import "package:flutter/widgets.dart";
@@ -31,6 +29,7 @@ import "package:photos/models/preview/preview_item_status.dart";
import "package:photos/service_locator.dart";
import "package:photos/services/collections_service.dart";
import "package:photos/services/filedata/model/file_data.dart";
import "package:photos/services/isolated_ffmpeg_service.dart";
import "package:photos/ui/notification/toast.dart";
import "package:photos/utils/exif_util.dart";
import "package:photos/utils/file_key.dart";
@@ -222,8 +221,6 @@ class VideoPreviewService {
'Generating HLS Playlist ${enteFile.displayName} at $prefix/output.m3u8}',
);
FFmpegSession? session;
final reencodeVideo =
!(isH264 && bitrate != null && bitrate <= 4000 * 1000);
final rescaleVideo = !(bitrate != null && bitrate <= 2000 * 1000);
@@ -270,21 +267,26 @@ class VideoPreviewService {
_logger.info(command);
session = await FFmpegKit.execute(
final map = await IsolatedFfmpegService.runFfmpeg(
// input file path
'-i "${file.path}" ' +
// main params for streaming
command +
// output file path
'$prefix/output.m3u8',
).onError(
(error, stackTrace) {
_logger.warning("FFmpeg command failed", error, stackTrace);
return {};
},
);
final returnCode = await session.getReturnCode();
final returnCode = map["returnCode"] as int?;
String? objectId;
int? objectSize;
if (ReturnCode.isSuccess(returnCode)) {
if (ReturnCode.success == returnCode) {
try {
_items[enteFile.uploadedFileID!] = PreviewItem(
status: PreviewItemStatus.uploading,
@@ -303,13 +305,22 @@ class VideoPreviewService {
objectSize = result.$2;
// Fetch resolution of generated stream by decrypting a single frame
final FFmpegSession session2 = await FFmpegKit.execute(
final map2 = await IsolatedFfmpegService.runFfmpeg(
'-allowed_extensions ALL -i "$prefix/output.m3u8" -frames:v 1 -c copy "$prefix/frame.ts"',
).onError(
(error, stackTrace) {
_logger.warning(
"FFmpeg command failed for frame",
error,
stackTrace,
);
return {};
},
);
final returnCode2 = await session2.getReturnCode();
final returnCode2 = map2["returnCode"] as int?;
int? width, height;
try {
if (ReturnCode.isSuccess(returnCode2)) {
if (ReturnCode.success == returnCode2) {
FFProbeProps? props2;
final file2 = File("$prefix/frame.ts");
@@ -335,11 +346,11 @@ class VideoPreviewService {
error = "Failed to upload video preview\nError: $err";
_logger.shout("Something went wrong with preview upload", err, sT);
}
} else if (ReturnCode.isCancel(returnCode)) {
} else if (ReturnCode.cancel == returnCode) {
_logger.warning("FFmpeg command cancelled");
error = "FFmpeg command cancelled";
} else {
final output = await session.getOutput();
final output = map["output"] as String?;
_logger.shout(
"FFmpeg command failed with return code $returnCode",
output ?? "Error not found",
@@ -376,7 +387,9 @@ class VideoPreviewService {
if (uploadingFileId == enteFile.uploadedFileID!) {
uploadingFileId = -1;
}
_logger.info("[chunk] Processing ${_items.length} items for streaming");
_logger.info(
"[chunk] Processing ${_items.length} items for streaming, $error",
);
// process next file
if (fileQueue.isNotEmpty) {
final entry = fileQueue.entries.first;

View File

@@ -249,7 +249,11 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
}
_recoveryKeyFile.writeAsStringSync(recoveryKey);
await Share.shareXFiles([XFile(_recoveryKeyFile.path)]);
await SharePlus.instance.share(
ShareParams(
files: [XFile(_recoveryKeyFile.path)],
),
);
Future.delayed(const Duration(milliseconds: 500), () {
if (mounted) {
setState(() {

View File

@@ -83,7 +83,7 @@ class _SessionsPageState extends State<SessionsPage> {
color: Theme.of(context)
.colorScheme
.onSurface
.withOpacity(0.8),
.withValues(alpha: 0.8),
fontSize: 14,
),
),
@@ -96,7 +96,7 @@ class _SessionsPageState extends State<SessionsPage> {
color: Theme.of(context)
.colorScheme
.onSurface
.withOpacity(0.8),
.withValues(alpha: 0.8),
fontSize: 12,
),
),

View File

@@ -101,8 +101,9 @@ class _TwoFactorRecoveryPageState extends State<TwoFactorRecoveryPage> {
style: TextStyle(
decoration: TextDecoration.underline,
fontSize: 12,
color:
getEnteColorScheme(context).textBase.withOpacity(0.9),
color: getEnteColorScheme(context)
.textBase
.withValues(alpha: 0.9),
),
),
),

View File

@@ -160,14 +160,14 @@ class _TwoFactorSetupPageState extends State<TwoFactorSetupPage>
padding: const EdgeInsets.only(left: 10, right: 10),
child: Container(
padding: const EdgeInsets.all(16),
color: textColor.withOpacity(0.1),
color: textColor.withValues(alpha: 0.1),
child: Center(
child: Text(
widget.secretCode,
style: TextStyle(
fontSize: 15,
fontFeatures: const [FontFeature.tabularFigures()],
color: textColor.withOpacity(0.7),
color: textColor.withValues(alpha: 0.7),
),
),
),
@@ -176,7 +176,7 @@ class _TwoFactorSetupPageState extends State<TwoFactorSetupPage>
const Padding(padding: EdgeInsets.all(6)),
Text(
S.of(context).tapToCopy,
style: TextStyle(color: textColor.withOpacity(0.5)),
style: TextStyle(color: textColor.withValues(alpha: 0.5)),
),
],
),

View File

@@ -183,14 +183,14 @@ extension CollectionFileActions on CollectionActions {
}
Future<bool> addToCollection(
BuildContext context,
BuildContext? context,
int collectionID,
bool showProgressDialog, {
List<EnteFile>? selectedFiles,
List<SharedMediaFile>? sharedFiles,
List<AssetEntity>? picketAssets,
}) async {
ProgressDialog? dialog = showProgressDialog
ProgressDialog? dialog = showProgressDialog && context != null
? createProgressDialog(
context,
S.of(context).uploadingFilesToAlbum,
@@ -246,7 +246,7 @@ extension CollectionFileActions on CollectionActions {
final Collection? c =
CollectionsService.instance.getCollectionByID(collectionID);
if (c != null && c.owner.id != currentUserID) {
if (!showProgressDialog) {
if (!showProgressDialog && context != null) {
dialog = createProgressDialog(
context,
S.of(context).uploadingFilesToAlbum,
@@ -291,7 +291,9 @@ extension CollectionFileActions on CollectionActions {
} catch (e, s) {
logger.severe("Failed to add to album", e, s);
await dialog?.hide();
await showGenericErrorDialog(context: context, error: e);
if (context != null) {
await showGenericErrorDialog(context: context, error: e);
}
rethrow;
}
}

View File

@@ -120,8 +120,8 @@ class AlbumRowItemWidget extends StatelessWidget {
child: isSelected
? ColorFiltered(
colorFilter: ColorFilter.mode(
Colors.black.withOpacity(
0.4,
Colors.black.withValues(
alpha: 0.4,
),
BlendMode.darken,
),

View File

@@ -0,0 +1,182 @@
import "dart:async";
import 'package:flutter/material.dart';
import "package:photos/db/files_db.dart";
import "package:photos/generated/l10n.dart";
import "package:photos/models/collection/smart_album_config.dart";
import "package:photos/models/selected_people.dart";
import "package:photos/services/collections_service.dart";
import "package:photos/services/smart_albums_service.dart";
import "package:photos/ui/actions/collection/collection_sharing_actions.dart";
import "package:photos/ui/components/buttons/button_widget.dart";
import "package:photos/ui/components/models/button_type.dart";
import 'package:photos/ui/components/title_bar_title_widget.dart';
import 'package:photos/ui/components/title_bar_widget.dart';
import "package:photos/ui/viewer/search/result/people_section_all_page.dart"
show PeopleSectionAllWidget;
import "package:photos/utils/dialog_util.dart";
class SmartAlbumPeople extends StatefulWidget {
const SmartAlbumPeople({
super.key,
required this.collectionId,
});
final int collectionId;
@override
State<SmartAlbumPeople> createState() => _SmartAlbumPeopleState();
}
class _SmartAlbumPeopleState extends State<SmartAlbumPeople> {
final _selectedPeople = SelectedPeople();
SmartAlbumConfig? currentConfig;
@override
void initState() {
super.initState();
getSelections();
}
Future<void> getSelections() async {
currentConfig =
await SmartAlbumsService.instance.getConfig(widget.collectionId);
if (currentConfig != null &&
currentConfig!.personIDs.isNotEmpty &&
mounted) {
_selectedPeople.select(currentConfig!.personIDs);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: Padding(
padding: EdgeInsets.fromLTRB(
16,
8,
16,
8 + MediaQuery.viewPaddingOf(context).bottom,
),
child: ListenableBuilder(
listenable: _selectedPeople,
builder: (context, _) {
return ButtonWidget(
buttonType: ButtonType.primary,
buttonSize: ButtonSize.large,
labelText: S.of(context).save,
shouldSurfaceExecutionStates: false,
onTap: () async {
final dialog = createProgressDialog(
context,
S.of(context).pleaseWait,
isDismissible: true,
);
if (_selectedPeople.personIds.length ==
currentConfig?.personIDs.length &&
_selectedPeople.personIds
.toSet()
.difference(currentConfig?.personIDs.toSet() ?? {})
.isEmpty) {
Navigator.pop(context);
return;
}
try {
await dialog.show();
SmartAlbumConfig newConfig;
if (currentConfig == null) {
final infoMap = <String, PersonInfo>{};
// Add files which are needed
for (final personId in _selectedPeople.personIds) {
infoMap[personId] = (updatedAt: 0, addedFiles: {});
}
newConfig = SmartAlbumConfig(
collectionId: widget.collectionId,
personIDs: _selectedPeople.personIds,
infoMap: infoMap,
);
} else {
final removedPersonIds = currentConfig!.personIDs
.toSet()
.difference(_selectedPeople.personIds.toSet())
.toList();
if (removedPersonIds.isNotEmpty) {
final toDelete =
await SmartAlbumsService.instance.removeFilesDialog(
context,
);
await dialog.show();
if (toDelete) {
for (final personId in removedPersonIds) {
final files =
currentConfig!.infoMap[personId]?.addedFiles;
final enteFiles = await FilesDB.instance
.getAllFilesGroupByCollectionID(
files?.toList() ?? [],
);
final collection = CollectionsService.instance
.getCollectionByID(widget.collectionId);
if (files?.isNotEmpty ?? false) {
await CollectionActions(CollectionsService.instance)
.moveFilesFromCurrentCollection(
context,
collection!,
enteFiles[widget.collectionId] ?? [],
isHidden: collection.isHidden(),
);
}
}
}
}
newConfig = await currentConfig!.getUpdatedConfig(
_selectedPeople.personIds,
);
}
await SmartAlbumsService.instance.saveConfig(newConfig);
SmartAlbumsService.instance.syncSmartAlbums().ignore();
await dialog.hide();
Navigator.pop(context);
} catch (e) {
await dialog.hide();
await showGenericErrorDialog(context: context, error: e);
}
},
);
},
),
),
body: CustomScrollView(
primary: false,
slivers: <Widget>[
TitleBarWidget(
flexibleSpaceTitle: TitleBarTitleWidget(
title: S.of(context).people,
),
expandedHeight: MediaQuery.textScalerOf(context).scale(120),
flexibleSpaceCaption: S.of(context).peopleWidgetDesc,
actionIcons: const [],
),
SliverFillRemaining(
child: PeopleSectionAllWidget(
selectedPeople: _selectedPeople,
namedOnly: true,
),
),
],
),
);
}
}

View File

@@ -28,7 +28,7 @@ class ArchivedCollectionsButton extends StatelessWidget {
padding: const EdgeInsets.all(0),
side: BorderSide(
width: 0.5,
color: Theme.of(context).iconTheme.color!.withOpacity(0.24),
color: Theme.of(context).iconTheme.color!.withValues(alpha: 0.24),
),
),
child: SizedBox(

View File

@@ -23,7 +23,7 @@ class HiddenCollectionsButtonWidget extends StatelessWidget {
padding: const EdgeInsets.all(0),
side: BorderSide(
width: 0.5,
color: Theme.of(context).iconTheme.color!.withOpacity(0.24),
color: Theme.of(context).iconTheme.color!.withValues(alpha: 0.24),
),
),
child: SizedBox(

View File

@@ -52,7 +52,7 @@ class _TrashSectionButtonState extends State<TrashSectionButton> {
padding: const EdgeInsets.all(0),
side: BorderSide(
width: 0.5,
color: Theme.of(context).iconTheme.color!.withOpacity(0.24),
color: Theme.of(context).iconTheme.color!.withValues(alpha: 0.24),
),
),
child: SizedBox(

View File

@@ -33,7 +33,7 @@ class UnCategorizedCollections extends StatelessWidget {
padding: const EdgeInsets.all(0),
side: BorderSide(
width: 0.5,
color: Theme.of(context).iconTheme.color!.withOpacity(0.24),
color: Theme.of(context).iconTheme.color!.withValues(alpha: 0.24),
),
),
child: SizedBox(

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