1
0
mirror of https://github.com/immich-app/immich.git synced 2024-12-25 10:43:13 +02:00

feat(mobile): Facial recognition (#2507)

* Add API service

* Added service, provider

* merge main

* update pubspec

* styling

* dev: add person search result page

* dev: display person asset on page

* dev: add rename form

* style form

* dev: mechanism to add name to faces

* styling

* fix bad merge

* update api

* test

* revert

* Add header widget

* change name

* show all people page

* fix test

* pr feedback

* Add name to app bar

* feedback

* styling
This commit is contained in:
Alex 2023-06-23 10:44:02 -05:00 committed by GitHub
parent 00f65a53dd
commit 0d0866d5d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 964 additions and 231 deletions

View File

@ -217,6 +217,7 @@
"search_page_selfies": "Selfies", "search_page_selfies": "Selfies",
"search_page_things": "Things", "search_page_things": "Things",
"search_page_videos": "Videos", "search_page_videos": "Videos",
"search_page_people": "People",
"search_page_view_all_button": "View all", "search_page_view_all_button": "View all",
"search_page_your_activity": "Your activity", "search_page_your_activity": "Your activity",
"search_result_page_new_search_hint": "New Search", "search_result_page_new_search_hint": "New Search",
@ -285,5 +286,6 @@
"version_announcement_overlay_text_1": "Hi friend, there is a new release of", "version_announcement_overlay_text_1": "Hi friend, there is a new release of",
"version_announcement_overlay_text_2": "please take your time to visit the ", "version_announcement_overlay_text_2": "please take your time to visit the ",
"version_announcement_overlay_text_3": " and ensure your docker-compose and .env setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your server application automatically.", "version_announcement_overlay_text_3": " and ensure your docker-compose and .env setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your server application automatically.",
"version_announcement_overlay_title": "New Server Version Available \uD83C\uDF89" "version_announcement_overlay_title": "New Server Version Available \uD83C\uDF89",
} "all_people_page_title": "People"
}

View File

@ -39,7 +39,7 @@ PODS:
- shared_preferences_foundation (0.0.1): - shared_preferences_foundation (0.0.1):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
- sqflite (0.0.2): - sqflite (0.0.3):
- Flutter - Flutter
- FMDB (>= 2.7.5) - FMDB (>= 2.7.5)
- Toast (4.0.0) - Toast (4.0.0)
@ -128,21 +128,21 @@ SPEC CHECKSUMS:
flutter_web_auth: c25208760459cec375a3c39f6a8759165ca0fa4d flutter_web_auth: c25208760459cec375a3c39f6a8759165ca0fa4d
fluttertoast: eb263d302cc92e04176c053d2385237e9f43fad0 fluttertoast: eb263d302cc92e04176c053d2385237e9f43fad0
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
image_picker_ios: 58b9c4269cb176f89acea5e5d043c9358f2d25f8 image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5
integration_test: 13825b8a9334a850581300559b8839134b124670 integration_test: 13825b8a9334a850581300559b8839134b124670
isar_flutter_libs: b69f437aeab9c521821c3f376198c4371fa21073 isar_flutter_libs: b69f437aeab9c521821c3f376198c4371fa21073
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9 path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02 path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
photo_manager: 4f6810b7dfc4feb03b461ac1a70dacf91fba7604 photo_manager: 4f6810b7dfc4feb03b461ac1a70dacf91fba7604
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68 share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
shared_preferences_foundation: 986fc17f3d3251412d18b0265f9c64113a8c2472 shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4 url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
video_player_avfoundation: 6d971a232d72e6ee25368378d48a079dea01f1cf video_player_avfoundation: 81e49bb3d9fb63dccf9fa0f6d877dc3ddbeac126
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
PODFILE CHECKSUM: 599d8aeb73728400c15364e734525722250a5382 PODFILE CHECKSUM: 599d8aeb73728400c15364e734525722250a5382

View File

@ -28,6 +28,7 @@ class ImmichAssetGrid extends HookConsumerWidget {
final bool showMultiSelectIndicator; final bool showMultiSelectIndicator;
final void Function(ItemPosition start, ItemPosition end)? final void Function(ItemPosition start, ItemPosition end)?
visibleItemsListener; visibleItemsListener;
final Widget? topWidget;
const ImmichAssetGrid({ const ImmichAssetGrid({
super.key, super.key,
@ -44,6 +45,7 @@ class ImmichAssetGrid extends HookConsumerWidget {
this.dynamicLayout, this.dynamicLayout,
this.showMultiSelectIndicator = true, this.showMultiSelectIndicator = true,
this.visibleItemsListener, this.visibleItemsListener,
this.topWidget,
}); });
@override @override
@ -125,6 +127,7 @@ class ImmichAssetGrid extends HookConsumerWidget {
settings.getSetting(AppSettingsEnum.dynamicLayout), settings.getSetting(AppSettingsEnum.dynamicLayout),
showMultiSelectIndicator: showMultiSelectIndicator, showMultiSelectIndicator: showMultiSelectIndicator,
visibleItemsListener: visibleItemsListener, visibleItemsListener: visibleItemsListener,
topWidget: topWidget,
), ),
), ),
), ),

View File

@ -206,6 +206,8 @@ class ImmichAssetGridViewState extends State<ImmichAssetGridView> {
key: ValueKey(section.offset), key: ValueKey(section.offset),
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
if (section.offset == 0 && widget.topWidget != null)
widget.topWidget!,
if (section.type == RenderAssetGridElementType.monthTitle) if (section.type == RenderAssetGridElementType.monthTitle)
_buildMonthTitle(context, section.date), _buildMonthTitle(context, section.date),
if (section.type == RenderAssetGridElementType.groupDividerTitle || if (section.type == RenderAssetGridElementType.groupDividerTitle ||
@ -401,6 +403,7 @@ class ImmichAssetGridView extends StatefulWidget {
final bool showMultiSelectIndicator; final bool showMultiSelectIndicator;
final void Function(ItemPosition start, ItemPosition end)? final void Function(ItemPosition start, ItemPosition end)?
visibleItemsListener; visibleItemsListener;
final Widget? topWidget;
const ImmichAssetGridView({ const ImmichAssetGridView({
super.key, super.key,
@ -416,6 +419,7 @@ class ImmichAssetGridView extends StatefulWidget {
this.dynamicLayout = true, this.dynamicLayout = true,
this.showMultiSelectIndicator = true, this.showMultiSelectIndicator = true,
this.visibleItemsListener, this.visibleItemsListener,
this.topWidget,
}); });
@override @override

View File

@ -0,0 +1,44 @@
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/home/ui/asset_grid/asset_grid_data_structure.dart';
import 'package:immich_mobile/modules/search/services/person.service.dart';
import 'package:openapi/api.dart';
final personAssetsProvider = FutureProvider.family
.autoDispose<RenderList, String>((ref, personId) async {
final PersonService personService = ref.watch(personServiceProvider);
final assets = await personService.getPersonAssets(personId);
if (assets == null) {
return RenderList.empty();
}
return RenderList.fromAssets(assets, GroupAssetsBy.auto);
});
final getCuratedPeopleProvider =
FutureProvider.autoDispose<List<PersonResponseDto>>((ref) async {
final PersonService personService = ref.watch(personServiceProvider);
final curatedPeople = await personService.getCuratedPeople();
return curatedPeople ?? [];
});
class UpdatePersonName {
final String id;
final String name;
UpdatePersonName(this.id, this.name);
}
final updatePersonNameProvider =
StateProvider.family<void, UpdatePersonName>((ref, dto) async {
final PersonService personService = ref.watch(personServiceProvider);
final person = await personService.updateName(dto.id, dto.name);
if (person != null && person.name == dto.name) {
ref.invalidate(getCuratedPeopleProvider);
}
});

View File

@ -0,0 +1,56 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/shared/models/asset.dart';
import 'package:immich_mobile/shared/providers/api.provider.dart';
import 'package:immich_mobile/shared/services/api.service.dart';
import 'package:openapi/api.dart';
final personServiceProvider = Provider(
(ref) => PersonService(
ref.watch(apiServiceProvider),
),
);
class PersonService {
final ApiService _apiService;
PersonService(this._apiService);
Future<List<PersonResponseDto>?> getCuratedPeople() async {
try {
return await _apiService.personApi.getAllPeople();
} catch (e) {
debugPrint("Error [getCuratedPeople] ${e.toString()}");
return null;
}
}
Future<List<Asset>?> getPersonAssets(String id) async {
try {
final assets = await _apiService.personApi.getPersonAssets(id);
if (assets == null) {
return null;
}
return assets.map((e) => Asset.remote(e)).toList();
} catch (e) {
debugPrint("Error [getPersonAssets] ${e.toString()}");
return null;
}
}
Future<PersonResponseDto?> updateName(String id, String name) async {
try {
return await _apiService.personApi.updatePerson(
id,
PersonUpdateDto(
name: name,
),
);
} catch (e) {
debugPrint("Error [updateName] ${e.toString()}");
return null;
}
}
}

View File

@ -0,0 +1,114 @@
import 'package:flutter/material.dart';
import 'package:immich_mobile/modules/search/models/curated_content.dart';
import 'package:immich_mobile/modules/search/ui/thumbnail_with_info.dart';
import 'package:immich_mobile/shared/models/store.dart';
import 'package:immich_mobile/utils/image_url_builder.dart';
class CuratedPeopleRow extends StatelessWidget {
final List<CuratedContent> content;
/// Callback with the content and the index when tapped
final Function(CuratedContent, int)? onTap;
final Function(CuratedContent, int)? onNameTap;
const CuratedPeopleRow({
super.key,
required this.content,
this.onTap,
required this.onNameTap,
});
@override
Widget build(BuildContext context) {
const imageSize = 85.0;
// Guard empty [content]
if (content.isEmpty) {
// Return empty thumbnail
return Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: SizedBox(
width: imageSize,
height: imageSize,
child: ThumbnailWithInfo(
textInfo: '',
onTap: () {},
),
),
),
);
}
return ListView.builder(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.only(
left: 16,
top: 8,
),
itemBuilder: (context, index) {
final person = content[index];
final headers = {
"Authorization": "Bearer ${Store.get(StoreKey.accessToken)}"
};
return Padding(
padding: const EdgeInsets.only(right: 18.0),
child: SizedBox(
width: imageSize,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
GestureDetector(
onTap: () => onTap?.call(person, index),
child: SizedBox(
height: imageSize,
child: Material(
shape: const CircleBorder(side: BorderSide.none),
elevation: 3,
child: CircleAvatar(
maxRadius: imageSize / 2,
backgroundImage: NetworkImage(
getFaceThumbnailUrl(person.id),
headers: headers,
),
),
),
),
),
if (person.label == "")
GestureDetector(
onTap: () => onNameTap?.call(person, index),
child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(
"Add name",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Theme.of(context).primaryColor,
),
),
),
)
else
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(
person.label,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 13.0,
),
),
)
],
),
),
);
},
itemCount: content.length,
);
}
}

View File

@ -4,12 +4,16 @@ import 'package:immich_mobile/modules/search/models/curated_content.dart';
import 'package:immich_mobile/modules/search/ui/thumbnail_with_info.dart'; import 'package:immich_mobile/modules/search/ui/thumbnail_with_info.dart';
import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/shared/models/store.dart'; import 'package:immich_mobile/shared/models/store.dart';
import 'package:immich_mobile/utils/image_url_builder.dart';
class ExploreGrid extends StatelessWidget { class ExploreGrid extends StatelessWidget {
final List<CuratedContent> curatedContent; final List<CuratedContent> curatedContent;
final bool isPeople;
const ExploreGrid({ const ExploreGrid({
super.key, super.key,
required this.curatedContent, required this.curatedContent,
this.isPeople = false,
}); });
@override @override
@ -36,16 +40,25 @@ class ExploreGrid extends StatelessWidget {
), ),
itemBuilder: (context, index) { itemBuilder: (context, index) {
final content = curatedContent[index]; final content = curatedContent[index];
final thumbnailRequestUrl = final thumbnailRequestUrl = isPeople
'${Store.get(StoreKey.serverEndpoint)}/asset/thumbnail/${content.id}'; ? getFaceThumbnailUrl(content.id)
: '${Store.get(StoreKey.serverEndpoint)}/asset/thumbnail/${content.id}';
return ThumbnailWithInfo( return ThumbnailWithInfo(
imageUrl: thumbnailRequestUrl, imageUrl: thumbnailRequestUrl,
textInfo: content.label, textInfo: content.label,
borderRadius: 0, borderRadius: 0,
onTap: () { onTap: () {
AutoRouter.of(context).push( isPeople
SearchResultRoute(searchTerm: 'm:${content.label}'), ? AutoRouter.of(context).push(
); PersonResultRoute(
personId: content.id,
personName: content.label,
),
)
: AutoRouter.of(context).push(
SearchResultRoute(searchTerm: 'm:${content.label}'),
);
}, },
); );
}, },

View File

@ -0,0 +1,82 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/search/providers/people.provider.dart';
class PersonNameEditFormResult {
final bool success;
final String updatedName;
PersonNameEditFormResult(this.success, this.updatedName);
}
class PersonNameEditForm extends HookConsumerWidget {
final String personId;
final String personName;
const PersonNameEditForm({
super.key,
required this.personId,
required this.personName,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final controller = useTextEditingController(text: personName);
return AlertDialog(
title: const Text(
"Add a name",
style: TextStyle(fontWeight: FontWeight.bold),
),
content: SingleChildScrollView(
child: TextFormField(
controller: controller,
autofocus: true,
decoration: const InputDecoration(
hintText: 'Name',
),
),
),
actions: [
TextButton(
style: TextButton.styleFrom(),
onPressed: () {
Navigator.of(context, rootNavigator: true)
.pop<PersonNameEditFormResult>(
PersonNameEditFormResult(false, ''),
);
},
child: Text(
"Cancel",
style: TextStyle(
color: Colors.red[300],
fontWeight: FontWeight.bold,
),
),
),
TextButton(
onPressed: () {
ref.read(
updatePersonNameProvider(
UpdatePersonName(personId, controller.text),
),
);
Navigator.of(context, rootNavigator: true)
.pop<PersonNameEditFormResult>(
PersonNameEditFormResult(true, controller.text),
);
},
child: Text(
"Save",
style: TextStyle(
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.bold,
),
),
),
],
);
}
}

View File

@ -0,0 +1,46 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
class SearchRowTitle extends StatelessWidget {
final Function() onViewAllPressed;
final String title;
final double top;
const SearchRowTitle({
super.key,
required this.onViewAllPressed,
required this.title,
this.top = 12,
});
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(
left: 16.0,
right: 16.0,
top: top,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
title,
style: Theme.of(context).textTheme.titleSmall,
),
TextButton(
onPressed: onViewAllPressed,
child: Text(
'search_page_view_all_button',
style: TextStyle(
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.bold,
fontSize: 14.0,
),
).tr(),
),
],
),
);
}
}

View File

@ -0,0 +1,51 @@
import 'package:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/search/models/curated_content.dart';
import 'package:immich_mobile/modules/search/providers/people.provider.dart';
import 'package:immich_mobile/modules/search/ui/explore_grid.dart';
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
class AllPeoplePage extends HookConsumerWidget {
const AllPeoplePage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final curatedPeople = ref.watch(getCuratedPeopleProvider);
return Scaffold(
appBar: AppBar(
title: Text(
'all_people_page_title',
style: TextStyle(
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.bold,
fontSize: 16.0,
),
).tr(),
leading: IconButton(
onPressed: () => AutoRouter.of(context).pop(),
icon: const Icon(Icons.arrow_back_ios_rounded),
),
),
body: curatedPeople.when(
loading: () => const Center(child: ImmichLoadingIndicator()),
error: (err, stack) => Center(
child: Text('Error: $err'),
),
data: (people) => ExploreGrid(
isPeople: true,
curatedContent: people
.map(
(person) => CuratedContent(
label: person.name,
id: person.id,
),
)
.toList(),
),
),
);
}
}

View File

@ -0,0 +1,152 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
import 'package:immich_mobile/modules/search/providers/people.provider.dart';
import 'package:immich_mobile/modules/search/ui/person_name_edit_form.dart';
import 'package:immich_mobile/shared/models/store.dart' as isar_store;
import 'package:immich_mobile/utils/image_url_builder.dart';
class PersonResultPage extends HookConsumerWidget {
final String personId;
final String personName;
const PersonResultPage({
super.key,
required this.personId,
required this.personName,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final name = useState(personName);
showEditNameDialog() {
showDialog<PersonNameEditFormResult>(
context: context,
builder: (BuildContext context) {
return PersonNameEditForm(
personId: personId,
personName: personName,
);
},
).then((result) {
if (result != null && result.success) {
name.value = result.updatedName;
}
});
}
void buildBottomSheet() {
showModalBottomSheet(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
isScrollControlled: false,
context: context,
useSafeArea: true,
builder: (context) {
return SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: const Icon(Icons.edit_outlined),
title: const Text(
'Edit name',
style: TextStyle(fontWeight: FontWeight.bold),
),
onTap: showEditNameDialog,
)
],
),
);
},
);
}
buildTitleBlock() {
if (name.value == "") {
return GestureDetector(
onTap: showEditNameDialog,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Add a name',
style: Theme.of(context).textTheme.titleSmall?.copyWith(
color: Theme.of(context).colorScheme.secondary,
),
),
Text(
'Find them fast by name with search',
style: Theme.of(context).textTheme.labelSmall,
),
],
),
);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
name.value,
style: Theme.of(context).textTheme.titleLarge,
),
],
);
}
return Scaffold(
appBar: AppBar(
title: Text(name.value),
leading: IconButton(
onPressed: () => AutoRouter.of(context).pop(),
icon: const Icon(Icons.arrow_back_ios_rounded),
),
actions: [
IconButton(
onPressed: buildBottomSheet,
icon: const Icon(Icons.more_vert_rounded),
),
],
),
body: ref.watch(personAssetsProvider(personId)).when(
loading: () => const Center(child: CircularProgressIndicator()),
error: (error, stackTrace) => Center(
child: Text(
error.toString(),
),
),
data: (data) => data.isEmpty
? const Center(
child: Text('Opps'),
)
: ImmichAssetGrid(
renderList: data,
topWidget: Padding(
padding: const EdgeInsets.only(left: 8.0, top: 24),
child: Row(
children: [
CircleAvatar(
radius: 36,
backgroundImage: NetworkImage(
getFaceThumbnailUrl(personId),
headers: {
"Authorization":
"Bearer ${isar_store.Store.get(isar_store.StoreKey.accessToken)}"
},
),
),
Padding(
padding: const EdgeInsets.only(left: 16.0),
child: buildTitleBlock(),
),
],
),
),
),
),
);
}
}

View File

@ -4,13 +4,16 @@ import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart' hide Store; import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/search/models/curated_content.dart'; import 'package:immich_mobile/modules/search/models/curated_content.dart';
import 'package:immich_mobile/modules/search/providers/people.provider.dart';
import 'package:immich_mobile/modules/search/providers/search_page_state.provider.dart'; import 'package:immich_mobile/modules/search/providers/search_page_state.provider.dart';
import 'package:immich_mobile/modules/search/ui/curated_people_row.dart';
import 'package:immich_mobile/modules/search/ui/curated_row.dart'; import 'package:immich_mobile/modules/search/ui/curated_row.dart';
import 'package:immich_mobile/modules/search/ui/immich_search_bar.dart'; import 'package:immich_mobile/modules/search/ui/immich_search_bar.dart';
import 'package:immich_mobile/modules/search/ui/person_name_edit_form.dart';
import 'package:immich_mobile/modules/search/ui/search_row_title.dart';
import 'package:immich_mobile/modules/search/ui/search_suggestion_list.dart'; import 'package:immich_mobile/modules/search/ui/search_suggestion_list.dart';
import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart'; import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
import 'package:openapi/api.dart';
// ignore: must_be_immutable // ignore: must_be_immutable
class SearchPage extends HookConsumerWidget { class SearchPage extends HookConsumerWidget {
@ -21,10 +24,9 @@ class SearchPage extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final isSearchEnabled = ref.watch(searchPageStateProvider).isSearchEnabled; final isSearchEnabled = ref.watch(searchPageStateProvider).isSearchEnabled;
AsyncValue<List<CuratedLocationsResponseDto>> curatedLocation = final curatedLocation = ref.watch(getCuratedLocationProvider);
ref.watch(getCuratedLocationProvider); final curatedObjects = ref.watch(getCuratedObjectProvider);
AsyncValue<List<CuratedObjectsResponseDto>> curatedObjects = final curatedPeople = ref.watch(getCuratedPeopleProvider);
ref.watch(getCuratedObjectProvider);
var isDarkTheme = Theme.of(context).brightness == Brightness.dark; var isDarkTheme = Theme.of(context).brightness == Brightness.dark;
double imageSize = MediaQuery.of(context).size.width / 3; double imageSize = MediaQuery.of(context).size.width / 3;
@ -54,6 +56,50 @@ class SearchPage extends HookConsumerWidget {
); );
} }
showNameEditModel(
String personId,
String personName,
) {
return showDialog(
context: context,
builder: (BuildContext context) {
return PersonNameEditForm(personId: personId, personName: personName);
},
);
}
buildPeople() {
return SizedBox(
height: MediaQuery.of(context).size.width / 3,
child: curatedPeople.when(
loading: () => const Center(child: ImmichLoadingIndicator()),
error: (err, stack) => Center(child: Text('Error: $err')),
data: (people) => CuratedPeopleRow(
content: people
.map(
(person) => CuratedContent(
id: person.id,
label: person.name,
),
)
.take(12)
.toList(),
onTap: (content, index) {
AutoRouter.of(context).push(
PersonResultRoute(
personId: content.id,
personName: content.label,
),
);
},
onNameTap: (person, index) => {
showNameEditModel(person.id, person.label),
},
),
),
);
}
buildPlaces() { buildPlaces() {
return SizedBox( return SizedBox(
height: imageSize, height: imageSize,
@ -130,63 +176,25 @@ class SearchPage extends HookConsumerWidget {
children: [ children: [
ListView( ListView(
children: [ children: [
Padding( SearchRowTitle(
padding: const EdgeInsets.symmetric( title: "search_page_people".tr(),
horizontal: 16.0, onViewAllPressed: () => AutoRouter.of(context).push(
vertical: 4.0, const AllPeopleRoute(),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"search_page_places",
style: Theme.of(context).textTheme.titleSmall,
).tr(),
TextButton(
child: Text(
'search_page_view_all_button',
style: TextStyle(
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.bold,
fontSize: 14.0,
),
).tr(),
onPressed: () => AutoRouter.of(context).push(
const CuratedLocationRoute(),
),
),
],
), ),
), ),
buildPlaces(), buildPeople(),
Padding( SearchRowTitle(
padding: const EdgeInsets.only( title: "search_page_places".tr(),
top: 24.0, onViewAllPressed: () => AutoRouter.of(context).push(
bottom: 4.0, const CuratedLocationRoute(),
left: 16.0,
right: 16.0,
), ),
child: Row( top: 0,
mainAxisAlignment: MainAxisAlignment.spaceBetween, ),
children: [ buildPlaces(),
Text( SearchRowTitle(
"search_page_things", title: "search_page_things".tr(),
style: Theme.of(context).textTheme.titleSmall, onViewAllPressed: () => AutoRouter.of(context).push(
).tr(), const CuratedObjectRoute(),
TextButton(
child: Text(
'search_page_view_all_button',
style: TextStyle(
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.bold,
fontSize: 14.0,
),
).tr(),
onPressed: () => AutoRouter.of(context).push(
const CuratedObjectRoute(),
),
),
],
), ),
), ),
buildThings(), buildThings(),
@ -200,7 +208,7 @@ class SearchPage extends HookConsumerWidget {
), ),
ListTile( ListTile(
leading: Icon( leading: Icon(
Icons.favorite_border, Icons.star_outline,
color: categoryIconColor, color: categoryIconColor,
), ),
title: title:

View File

@ -25,9 +25,11 @@ import 'package:immich_mobile/modules/login/views/login_page.dart';
import 'package:immich_mobile/modules/onboarding/providers/gallery_permission.provider.dart'; import 'package:immich_mobile/modules/onboarding/providers/gallery_permission.provider.dart';
import 'package:immich_mobile/modules/onboarding/views/permission_onboarding_page.dart'; import 'package:immich_mobile/modules/onboarding/views/permission_onboarding_page.dart';
import 'package:immich_mobile/modules/search/views/all_motion_videos_page.dart'; import 'package:immich_mobile/modules/search/views/all_motion_videos_page.dart';
import 'package:immich_mobile/modules/search/views/all_people_page.dart';
import 'package:immich_mobile/modules/search/views/all_videos_page.dart'; import 'package:immich_mobile/modules/search/views/all_videos_page.dart';
import 'package:immich_mobile/modules/search/views/curated_location_page.dart'; import 'package:immich_mobile/modules/search/views/curated_location_page.dart';
import 'package:immich_mobile/modules/search/views/curated_object_page.dart'; import 'package:immich_mobile/modules/search/views/curated_object_page.dart';
import 'package:immich_mobile/modules/search/views/person_result_page.dart';
import 'package:immich_mobile/modules/search/views/recently_added_page.dart'; import 'package:immich_mobile/modules/search/views/recently_added_page.dart';
import 'package:immich_mobile/modules/search/views/search_page.dart'; import 'package:immich_mobile/modules/search/views/search_page.dart';
import 'package:immich_mobile/modules/search/views/search_result_page.dart'; import 'package:immich_mobile/modules/search/views/search_result_page.dart';
@ -37,8 +39,8 @@ import 'package:immich_mobile/routing/duplicate_guard.dart';
import 'package:immich_mobile/routing/gallery_permission_guard.dart'; import 'package:immich_mobile/routing/gallery_permission_guard.dart';
import 'package:immich_mobile/shared/models/asset.dart'; import 'package:immich_mobile/shared/models/asset.dart';
import 'package:immich_mobile/shared/models/album.dart'; import 'package:immich_mobile/shared/models/album.dart';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:immich_mobile/shared/models/logger_message.model.dart'; import 'package:immich_mobile/shared/models/logger_message.model.dart';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:immich_mobile/shared/providers/api.provider.dart'; import 'package:immich_mobile/shared/providers/api.provider.dart';
import 'package:immich_mobile/shared/services/api.service.dart'; import 'package:immich_mobile/shared/services/api.service.dart';
import 'package:immich_mobile/shared/views/app_log_detail_page.dart'; import 'package:immich_mobile/shared/views/app_log_detail_page.dart';
@ -140,7 +142,15 @@ part 'router.gr.dart';
], ],
), ),
AutoRoute(page: PartnerPage, guards: [AuthGuard, DuplicateGuard]), AutoRoute(page: PartnerPage, guards: [AuthGuard, DuplicateGuard]),
AutoRoute(page: PartnerDetailPage, guards: [AuthGuard, DuplicateGuard]) AutoRoute(page: PartnerDetailPage, guards: [AuthGuard, DuplicateGuard]),
AutoRoute(
page: PersonResultPage,
guards: [
AuthGuard,
DuplicateGuard,
],
),
AutoRoute(page: AllPeoplePage, guards: [AuthGuard, DuplicateGuard]),
], ],
) )
class AppRouter extends _$AppRouter { class AppRouter extends _$AppRouter {

View File

@ -84,6 +84,7 @@ class _$AppRouter extends RootStackRouter {
onVideoEnded: args.onVideoEnded, onVideoEnded: args.onVideoEnded,
onPlaying: args.onPlaying, onPlaying: args.onPlaying,
onPaused: args.onPaused, onPaused: args.onPaused,
placeholder: args.placeholder,
), ),
); );
}, },
@ -272,6 +273,23 @@ class _$AppRouter extends RootStackRouter {
), ),
); );
}, },
PersonResultRoute.name: (routeData) {
final args = routeData.argsAs<PersonResultRouteArgs>();
return MaterialPageX<dynamic>(
routeData: routeData,
child: PersonResultPage(
key: args.key,
personId: args.personId,
personName: args.personName,
),
);
},
AllPeopleRoute.name: (routeData) {
return MaterialPageX<dynamic>(
routeData: routeData,
child: const AllPeoplePage(),
);
},
HomeRoute.name: (routeData) { HomeRoute.name: (routeData) {
return MaterialPageX<dynamic>( return MaterialPageX<dynamic>(
routeData: routeData, routeData: routeData,
@ -555,6 +573,22 @@ class _$AppRouter extends RootStackRouter {
duplicateGuard, duplicateGuard,
], ],
), ),
RouteConfig(
PersonResultRoute.name,
path: '/person-result-page',
guards: [
authGuard,
duplicateGuard,
],
),
RouteConfig(
AllPeopleRoute.name,
path: '/all-people-page',
guards: [
authGuard,
duplicateGuard,
],
),
]; ];
} }
@ -670,9 +704,10 @@ class VideoViewerRoute extends PageRouteInfo<VideoViewerRouteArgs> {
Key? key, Key? key,
required Asset asset, required Asset asset,
required bool isMotionVideo, required bool isMotionVideo,
required dynamic onVideoEnded, required void Function() onVideoEnded,
dynamic onPlaying, void Function()? onPlaying,
dynamic onPaused, void Function()? onPaused,
Widget? placeholder,
}) : super( }) : super(
VideoViewerRoute.name, VideoViewerRoute.name,
path: '/video-viewer-page', path: '/video-viewer-page',
@ -683,6 +718,7 @@ class VideoViewerRoute extends PageRouteInfo<VideoViewerRouteArgs> {
onVideoEnded: onVideoEnded, onVideoEnded: onVideoEnded,
onPlaying: onPlaying, onPlaying: onPlaying,
onPaused: onPaused, onPaused: onPaused,
placeholder: placeholder,
), ),
); );
@ -697,6 +733,7 @@ class VideoViewerRouteArgs {
required this.onVideoEnded, required this.onVideoEnded,
this.onPlaying, this.onPlaying,
this.onPaused, this.onPaused,
this.placeholder,
}); });
final Key? key; final Key? key;
@ -705,15 +742,17 @@ class VideoViewerRouteArgs {
final bool isMotionVideo; final bool isMotionVideo;
final dynamic onVideoEnded; final void Function() onVideoEnded;
final dynamic onPlaying; final void Function()? onPlaying;
final dynamic onPaused; final void Function()? onPaused;
final Widget? placeholder;
@override @override
String toString() { String toString() {
return 'VideoViewerRouteArgs{key: $key, asset: $asset, isMotionVideo: $isMotionVideo, onVideoEnded: $onVideoEnded, onPlaying: $onPlaying, onPaused: $onPaused}'; return 'VideoViewerRouteArgs{key: $key, asset: $asset, isMotionVideo: $isMotionVideo, onVideoEnded: $onVideoEnded, onPlaying: $onPlaying, onPaused: $onPaused, placeholder: $placeholder}';
} }
} }
@ -1191,6 +1230,57 @@ class PartnerDetailRouteArgs {
} }
} }
/// generated route for
/// [PersonResultPage]
class PersonResultRoute extends PageRouteInfo<PersonResultRouteArgs> {
PersonResultRoute({
Key? key,
required String personId,
required String personName,
}) : super(
PersonResultRoute.name,
path: '/person-result-page',
args: PersonResultRouteArgs(
key: key,
personId: personId,
personName: personName,
),
);
static const String name = 'PersonResultRoute';
}
class PersonResultRouteArgs {
const PersonResultRouteArgs({
this.key,
required this.personId,
required this.personName,
});
final Key? key;
final String personId;
final String personName;
@override
String toString() {
return 'PersonResultRouteArgs{key: $key, personId: $personId, personName: $personName}';
}
}
/// generated route for
/// [AllPeoplePage]
class AllPeopleRoute extends PageRouteInfo<void> {
const AllPeopleRoute()
: super(
AllPeopleRoute.name,
path: '/all-people-page',
);
static const String name = 'AllPeopleRoute';
}
/// generated route for /// generated route for
/// [HomePage] /// [HomePage]
class HomeRoute extends PageRouteInfo<void> { class HomeRoute extends PageRouteInfo<void> {

View File

@ -1,6 +1,7 @@
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/album/providers/album.provider.dart'; import 'package:immich_mobile/modules/album/providers/album.provider.dart';
import 'package:immich_mobile/modules/search/providers/people.provider.dart';
import 'package:immich_mobile/modules/search/providers/search_page_state.provider.dart'; import 'package:immich_mobile/modules/search/providers/search_page_state.provider.dart';
import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart'; import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart';
@ -32,6 +33,7 @@ class TabNavigationObserver extends AutoRouterObserver {
// Refresh Location State // Refresh Location State
ref.invalidate(getCuratedLocationProvider); ref.invalidate(getCuratedLocationProvider);
ref.invalidate(getCuratedObjectProvider); ref.invalidate(getCuratedObjectProvider);
ref.invalidate(getCuratedPeopleProvider);
} }
if (route.name == 'SharingRoute') { if (route.name == 'SharingRoute') {

View File

@ -17,6 +17,7 @@ class ApiService {
late SearchApi searchApi; late SearchApi searchApi;
late ServerInfoApi serverInfoApi; late ServerInfoApi serverInfoApi;
late PartnerApi partnerApi; late PartnerApi partnerApi;
late PersonApi personApi;
ApiService() { ApiService() {
final endpoint = Store.tryGet(StoreKey.serverEndpoint); final endpoint = Store.tryGet(StoreKey.serverEndpoint);
@ -39,6 +40,7 @@ class ApiService {
serverInfoApi = ServerInfoApi(_apiClient); serverInfoApi = ServerInfoApi(_apiClient);
searchApi = SearchApi(_apiClient); searchApi = SearchApi(_apiClient);
partnerApi = PartnerApi(_apiClient); partnerApi = PartnerApi(_apiClient);
personApi = PersonApi(_apiClient);
} }
Future<String> resolveAndSetEndpoint(String serverUrl) async { Future<String> resolveAndSetEndpoint(String serverUrl) async {

View File

@ -59,3 +59,7 @@ String _getThumbnailUrl(
}) { }) {
return '${Store.get(StoreKey.serverEndpoint)}/asset/thumbnail/$id?format=${type.value}'; return '${Store.get(StoreKey.serverEndpoint)}/asset/thumbnail/$id?format=${type.value}';
} }
String getFaceThumbnailUrl(final String personId) {
return '${Store.get(StoreKey.serverEndpoint)}/person/$personId/thumbnail';
}

View File

@ -32,6 +32,8 @@ ThemeData immichLightTheme = ThemeData(
primarySwatch: Colors.indigo, primarySwatch: Colors.indigo,
primaryColor: Colors.indigo, primaryColor: Colors.indigo,
hintColor: Colors.indigo, hintColor: Colors.indigo,
focusColor: Colors.indigo,
splashColor: Colors.indigo.withOpacity(0.15),
fontFamily: 'WorkSans', fontFamily: 'WorkSans',
scaffoldBackgroundColor: immichBackgroundColor, scaffoldBackgroundColor: immichBackgroundColor,
snackBarTheme: const SnackBarThemeData( snackBarTheme: const SnackBarThemeData(
@ -119,6 +121,26 @@ ThemeData immichLightTheme = ThemeData(
), ),
), ),
), ),
dialogTheme: const DialogTheme(
surfaceTintColor: Colors.transparent,
),
inputDecorationTheme: const InputDecorationTheme(
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.indigo,
),
),
labelStyle: TextStyle(
color: Colors.indigo,
),
hintStyle: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.normal,
),
),
textSelectionTheme: const TextSelectionThemeData(
cursorColor: Colors.indigo,
),
); );
ThemeData immichDarkTheme = ThemeData( ThemeData immichDarkTheme = ThemeData(
@ -217,4 +239,24 @@ ThemeData immichDarkTheme = ThemeData(
), ),
), ),
), ),
dialogTheme: const DialogTheme(
surfaceTintColor: Colors.transparent,
),
inputDecorationTheme: InputDecorationTheme(
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: immichDarkThemePrimaryColor,
),
),
labelStyle: TextStyle(
color: immichDarkThemePrimaryColor,
),
hintStyle: const TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.normal,
),
),
textSelectionTheme: TextSelectionThemeData(
cursorColor: immichDarkThemePrimaryColor,
),
); );

View File

@ -21,18 +21,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: archive name: archive
sha256: "80e5141fafcb3361653ce308776cfd7d45e6e9fbb429e14eec571382c0c5fecb" sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.3.2" version: "3.3.7"
args: args:
dependency: transitive dependency: transitive
description: description:
name: args name: args
sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440" sha256: c372bb384f273f0c2a8aaaa226dad84dc27c8519a691b888725dec59518ad53a
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.0" version: "2.4.1"
async: async:
dependency: transitive dependency: transitive
description: description:
@ -77,10 +77,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: build name: build
sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" sha256: "43865b79fbb78532e4bff7c33087aa43b1d488c4fdef014eaef568af6d8016dc"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.1" version: "2.4.0"
build_config: build_config:
dependency: transitive dependency: transitive
description: description:
@ -93,34 +93,34 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: build_daemon name: build_daemon
sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.0" version: "4.0.0"
build_resolvers: build_resolvers:
dependency: transitive dependency: transitive
description: description:
name: build_resolvers name: build_resolvers
sha256: "687cf90a3951affac1bd5f9ecb5e3e90b60487f3d9cdc359bb310f8876bb02a6" sha256: db49b8609ef8c81cca2b310618c3017c00f03a92af44c04d310b907b2d692d95
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.10" version: "2.2.0"
build_runner: build_runner:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 sha256: "220ae4553e50d7c21a17c051afc7b183d28a24a420502e842f303f8e4e6edced"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.3" version: "2.4.4"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
name: build_runner_core name: build_runner_core
sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" sha256: "30859c90e9ddaccc484f56303931f477b1f1ba2bab74aa32ed5d6ce15870f8cf"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.2.7" version: "7.2.8"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
@ -133,10 +133,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: built_value name: built_value
sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725" sha256: "2f17434bd5d52a26762043d6b43bb53b3acd029b4d9071a329f46d67ef297e6d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.4.3" version: "8.5.0"
cached_network_image: cached_network_image:
dependency: "direct main" dependency: "direct main"
description: description:
@ -165,18 +165,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: cancellation_token name: cancellation_token
sha256: "44891ef71d605bc59ef7974c403630d8e8506fcd897a29c3e38466ef69e5c4eb" sha256: "7bacc556338b9f84e4db991805fdfa37fa1eda3689b94185bdc7459099455d71"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.6.1" version: "2.0.0"
cancellation_token_http: cancellation_token_http:
dependency: "direct main" dependency: "direct main"
description: description:
name: cancellation_token_http name: cancellation_token_http
sha256: e0396730db74d96522cb7162cb390c73b3e30aa24450001a24374cd09f8484ea sha256: bb91655e2e47d6274b681261ee6a687b7aa9023f49cfc28f42d095b2f86febc3
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.0" version: "1.3.0"
characters: characters:
dependency: transitive dependency: transitive
description: description:
@ -189,18 +189,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: checked_yaml name: checked_yaml
sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.2" version: "2.0.3"
chewie: chewie:
dependency: "direct main" dependency: "direct main"
description: description:
name: chewie name: chewie
sha256: e9da4898ee4859825404f507969f57113c04ca0060e152b95c9afd73934126ad sha256: "745e81e84c6d7f3835f89f85bb49771c0a66099e4caf8f8e9e9a372bc66fb2c1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.0" version: "1.5.0"
clock: clock:
dependency: transitive dependency: transitive
description: description:
@ -269,10 +269,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: dart_style name: dart_style
sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" sha256: f4f1f73ab3fd2afcbcca165ee601fe980d966af6a21b5970c6c9376955c528ad
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.4" version: "2.3.1"
dartx: dartx:
dependency: transitive dependency: transitive
description: description:
@ -285,10 +285,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: device_info_plus name: device_info_plus
sha256: "1d6e5a61674ba3a68fb048a7c7b4ff4bebfed8d7379dbe8f2b718231be9a7c95" sha256: f52ab3b76b36ede4d135aab80194df8925b553686f0fa12226b4e2d658e45903
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.1.0" version: "8.2.2"
device_info_plus_platform_interface: device_info_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -309,10 +309,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: easy_localization name: easy_localization
sha256: f30e9b20ed4d1b890171c30241d9b9c43efe21fee55dee7bd68f94daf269ea75 sha256: "30ebf25448ffe169e0bd9bc4b5da94faa8398967a2ad2ca09f438be8b6953645"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.2-dev.2" version: "3.0.2"
easy_logger: easy_logger:
dependency: transitive dependency: transitive
description: description:
@ -436,18 +436,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: flutter_plugin_android_lifecycle name: flutter_plugin_android_lifecycle
sha256: "4bef634684b2c7f3468c77c766c831229af829a0cd2d4ee6c1b99558bd14e5d2" sha256: "950e77c2bbe1692bc0874fc7fb491b96a4dc340457f4ea1641443d0a6c1ea360"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.8" version: "2.0.15"
flutter_riverpod: flutter_riverpod:
dependency: transitive dependency: transitive
description: description:
name: flutter_riverpod name: flutter_riverpod
sha256: "46a27b7a11dc13738054093076f2dc65692ddcd463979b15092accf5681aea20" sha256: b83ac5827baadefd331ea1d85110f34645827ea234ccabf53a655f41901a9bf4
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.0" version: "2.3.6"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@ -507,26 +507,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: graphs name: graphs
sha256: f9e130f3259f52d26f0cfc0e964513796dafed572fa52e45d2f8d6ca14db39b2 sha256: "772db3d53d23361d4ffcf5a9bb091cf3ee9b22f2be52cd107cd7a2683a89ba0e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.0" version: "2.3.0"
hooks_riverpod: hooks_riverpod:
dependency: "direct main" dependency: "direct main"
description: description:
name: hooks_riverpod name: hooks_riverpod
sha256: a596bcb1eaf48eae6da1ce8b9e60ec9538ef7d15725e941c3626f29dfcc01d96 sha256: be68cf7653fcab798500f9047ac58c3f109287a1595012412f4a0d654a9bb9c5
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.0" version: "2.3.6"
html: html:
dependency: transitive dependency: transitive
description: description:
name: html name: html
sha256: d9793e10dbe0e6c364f4c59bf3e01fb33a9b2a674bc7a1081693dba0614b6269 sha256: "58e3491f7bf0b6a4ea5110c0c688877460d1a6366731155c4a4580e7ded773e8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.15.1" version: "0.15.3"
http: http:
dependency: "direct main" dependency: "direct main"
description: description:
@ -563,34 +563,34 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: image_picker name: image_picker
sha256: "22207768556b82d55ec70166824350fee32298732d5efa4d6e756f848f51f66a" sha256: "9978d3510af4e6a902e545ce19229b926e6de6a1828d6134d3aab2e129a4d270"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.8.6+3" version: "0.8.7+5"
image_picker_android: image_picker_android:
dependency: transitive dependency: transitive
description: description:
name: image_picker_android name: image_picker_android
sha256: "68d067baf7f6e401b1124ee83dd6967e67847314250fd68012aab34a69beb344" sha256: "364967c8d581f5d75fc05f6c79fcf1115e3c05db3d3eee1aaca52e0da3f7501c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.8.5+7" version: "0.8.6+15"
image_picker_for_web: image_picker_for_web:
dependency: transitive dependency: transitive
description: description:
name: image_picker_for_web name: image_picker_for_web
sha256: "66fc6e3877bbde82c33d122f3588777c3784ac5bd7d1cdd79213ef7aecb85b34" sha256: "98f50d6b9f294c8ba35e25cc0d13b04bfddd25dbc8d32fa9d566a6572f2c081c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.11" version: "2.1.12"
image_picker_ios: image_picker_ios:
dependency: transitive dependency: transitive
description: description:
name: image_picker_ios name: image_picker_ios
sha256: "39aa70b5f1e5e7c94585b9738632d5fdb764a5655e40cd9e7b95fbd2fc50c519" sha256: d779210bda268a03b57e923fb1e410f32f5c5e708ad256348bcbf1f44f558fd0
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.8.6+9" version: "0.8.7+4"
image_picker_platform_interface: image_picker_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -656,10 +656,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: json_annotation name: json_annotation
sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.8.0" version: "4.8.1"
latlong2: latlong2:
dependency: "direct main" dependency: "direct main"
description: description:
@ -672,10 +672,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: lints name: lints
sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" sha256: "6b0206b0bf4f04961fc5438198ccb3a885685cd67d4d4a32cc20ad7f8adbe015"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.1" version: "2.1.0"
lists: lists:
dependency: transitive dependency: transitive
description: description:
@ -799,26 +799,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: path_provider name: path_provider
sha256: "04890b994ee89bfa80bf3080bfec40d5a92c5c7a785ebb02c13084a099d2b6f9" sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.13" version: "2.0.15"
path_provider_android: path_provider_android:
dependency: transitive dependency: transitive
description: description:
name: path_provider_android name: path_provider_android
sha256: "7623b7d4be0f0f7d9a8b5ee6879fc13e4522d4c875ab86801dee4af32b54b83e" sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.23" version: "2.0.27"
path_provider_foundation: path_provider_foundation:
dependency: transitive dependency: transitive
description: description:
name: path_provider_foundation name: path_provider_foundation
sha256: eec003594f19fe2456ea965ae36b3fc967bc5005f508890aafe31fa75e41d972 sha256: "1995d88ec2948dac43edf8fe58eb434d35d22a2940ecee1a9fefcd62beee6eb3"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.2" version: "2.2.3"
path_provider_ios: path_provider_ios:
dependency: "direct main" dependency: "direct main"
description: description:
@ -831,10 +831,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: path_provider_linux name: path_provider_linux
sha256: "525ad5e07622d19447ad740b1ed5070031f7a5437f44355ae915ff56e986429a" sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.9" version: "2.1.10"
path_provider_platform_interface: path_provider_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -847,10 +847,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: path_provider_windows name: path_provider_windows
sha256: "642ddf65fde5404f83267e8459ddb4556316d3ee6d511ed193357e25caa3632d" sha256: d3f80b32e83ec208ac95253e0cd4d298e104fbc63cb29c5c69edaed43b0c69d6
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.1.6"
pedantic: pedantic:
dependency: transitive dependency: transitive
description: description:
@ -871,18 +871,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: permission_handler_android name: permission_handler_android
sha256: "8028362b40c4a45298f1cbfccd227c8dd6caf0e27088a69f2ba2ab15464159e2" sha256: d8cc6a62ded6d0f49c6eac337e080b066ee3bce4d405bd9439a61e1f1927bfe8
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.2.0" version: "10.2.1"
permission_handler_apple: permission_handler_apple:
dependency: transitive dependency: transitive
description: description:
name: permission_handler_apple name: permission_handler_apple
sha256: "9c370ef6a18b1c4b2f7f35944d644a56aa23576f23abee654cf73968de93f163" sha256: ee96ac32f5a8e6f80756e25b25b9f8e535816c8e6665a96b6d70681f8c4f7e85
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "9.0.7" version: "9.0.8"
permission_handler_platform_interface: permission_handler_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -903,18 +903,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: petitparser name: petitparser
sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.1.0" version: "5.4.0"
photo_manager: photo_manager:
dependency: "direct main" dependency: "direct main"
description: description:
name: photo_manager name: photo_manager
sha256: "55d50ad1b8f984c57fa7c4bd4980f4760e80d3d9355263cf72624a6ff1bf2b5b" sha256: bdc4ab1fa9fb064d8ccfea6ab44119f55b220293d7ce2e19eb5a5f998db86c88
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.5.2" version: "2.6.0"
platform: platform:
dependency: transitive dependency: transitive
description: description:
@ -931,6 +931,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.1.4"
pointycastle:
dependency: transitive
description:
name: pointycastle
sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
url: "https://pub.dev"
source: hosted
version: "3.7.3"
polylabel: polylabel:
dependency: transitive dependency: transitive
description: description:
@ -975,26 +983,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: pub_semver name: pub_semver
sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.3" version: "2.1.4"
pubspec_parse: pubspec_parse:
dependency: transitive dependency: transitive
description: description:
name: pubspec_parse name: pubspec_parse
sha256: "75f6614d6dde2dc68948dffbaa4fe5dae32cd700eb9fb763fe11dfb45a3c4d0a" sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.1" version: "1.2.3"
riverpod: riverpod:
dependency: transitive dependency: transitive
description: description:
name: riverpod name: riverpod
sha256: "59a48de9c757aa61aa28e9fd625ffb360d43b6b54606f12536622c55be9e8c4b" sha256: "80e48bebc83010d5e67a11c9514af6b44bbac1ec77b4333c8ea65dbc79e2d8ef"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.0" version: "2.3.6"
rxdart: rxdart:
dependency: transitive dependency: transitive
description: description:
@ -1007,98 +1015,98 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: scrollable_positioned_list name: scrollable_positioned_list
sha256: ca7fcaa743db712d4f7b1580526f494d0093c77a721a65705ee51fbeac7a2bd3 sha256: "1b54d5f1329a1e263269abc9e2543d90806131aa14fe7c6062a8054d57249287"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.5" version: "0.3.8"
share_plus: share_plus:
dependency: "direct main" dependency: "direct main"
description: description:
name: share_plus name: share_plus
sha256: "8c6892037b1824e2d7e8f59d54b3105932899008642e6372e5079c6939b4b625" sha256: b1f15232d41e9701ab2f04181f21610c36c83a12ae426b79b4bd011c567934b1
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.3.1" version: "6.3.4"
share_plus_platform_interface: share_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: share_plus_platform_interface name: share_plus_platform_interface
sha256: "82ddd4ab9260c295e6e39612d4ff00390b9a7a21f1bb1da771e2f232d80ab8a1" sha256: "0c6e61471bd71b04a138b8b588fa388e66d8b005e6f2deda63371c5c505a0981"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.0" version: "3.2.1"
shared_preferences: shared_preferences:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences name: shared_preferences
sha256: ee6257848f822b8481691f20c3e6d2bfee2e9eccb2a3d249907fcfb198c55b41 sha256: "16d3fb6b3692ad244a695c0183fca18cf81fd4b821664394a781de42386bf022"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.18" version: "2.1.1"
shared_preferences_android: shared_preferences_android:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_android name: shared_preferences_android
sha256: a51a4f9375097f94df1c6e0a49c0374440d31ab026b59d58a7e7660675879db4 sha256: "6478c6bbbecfe9aced34c483171e90d7c078f5883558b30ec3163cf18402c749"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.16" version: "2.1.4"
shared_preferences_foundation: shared_preferences_foundation:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_foundation name: shared_preferences_foundation
sha256: "6b84fdf06b32bb336f972d373cd38b63734f3461ba56ac2ba01b56d052796259" sha256: e014107bb79d6d3297196f4f2d0db54b5d1f85b8ea8ff63b8e8b391a02700feb
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.2.2"
shared_preferences_linux: shared_preferences_linux:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_linux name: shared_preferences_linux
sha256: d7fb71e6e20cd3dfffcc823a28da3539b392e53ed5fc5c2b90b55fdaa8a7e8fa sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.2.0"
shared_preferences_platform_interface: shared_preferences_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_platform_interface name: shared_preferences_platform_interface
sha256: "824bfd02713e37603b2bdade0842e47d56e7db32b1dcdd1cae533fb88e2913fc" sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.2.0"
shared_preferences_web: shared_preferences_web:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_web name: shared_preferences_web
sha256: "6737b757e49ba93de2a233df229d0b6a87728cea1684da828cbc718b65dcf9d7" sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.5" version: "2.1.0"
shared_preferences_windows: shared_preferences_windows:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_windows name: shared_preferences_windows
sha256: bd014168e8484837c39ef21065b78f305810ceabc1d4f90be6e3b392ce81b46d sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.2.0"
shelf: shelf:
dependency: transitive dependency: transitive
description: description:
name: shelf name: shelf
sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.0" version: "1.4.1"
shelf_web_socket: shelf_web_socket:
dependency: transitive dependency: transitive
description: description:
name: shelf_web_socket name: shelf_web_socket
sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.3" version: "1.0.4"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -1108,26 +1116,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: socket_io_client name: socket_io_client
sha256: a9c589d3fe2658506be38ddb36f23348daab73a00ff1645533669d07a5111cfc sha256: "5d2a0a12c2a4a5f48d14e5b6aef7db78d3b425a9b084071059fa54bd12d2576c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.1" version: "2.0.2"
socket_io_common: socket_io_common:
dependency: transitive dependency: transitive
description: description:
name: socket_io_common name: socket_io_common
sha256: "5a218a784df4d1927ae713e17af619caa736cb2ebac287c59e4e24228b22da29" sha256: "2ab92f8ff3ebbd4b353bf4a98bee45cc157e3255464b2f90f66e09c4472047eb"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.2" version: "2.0.3"
source_gen: source_gen:
dependency: transitive dependency: transitive
description: description:
name: source_gen name: source_gen
sha256: "2d79738b6bbf38a43920e2b8d189e9a3ce6cc201f4b8fc76be5e4fe377b1c38d" sha256: "373f96cf5a8744bc9816c1ff41cf5391bbdbe3d7a96fe98c622b6738a8a7bd33"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.6" version: "1.3.2"
source_span: source_span:
dependency: transitive dependency: transitive
description: description:
@ -1140,18 +1148,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: sqflite name: sqflite
sha256: "78324387dc81df14f78df06019175a86a2ee0437624166c382e145d0a7fd9a4f" sha256: b4d6710e1200e96845747e37338ea8a819a12b51689a3bcf31eff0003b37a0b9
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.4+1" version: "2.2.8+4"
sqflite_common: sqflite_common:
dependency: transitive dependency: transitive
description: description:
name: sqflite_common name: sqflite_common
sha256: bfd6973aaeeb93475bc0d875ac9aefddf7965ef22ce09790eb963992ffc5183f sha256: e77abf6ff961d69dfef41daccbb66b51e9983cdd5cb35bf30733598057401555
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.2+2" version: "2.4.5"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
@ -1204,10 +1212,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: synchronized name: synchronized
sha256: "33b31b6beb98100bf9add464a36a8dd03eb10c7a8cf15aeec535e9b054aaf04b" sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.1" version: "3.1.0"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description:
@ -1252,10 +1260,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: typed_data name: typed_data
sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.1" version: "1.3.2"
unicode: unicode:
dependency: transitive dependency: transitive
description: description:
@ -1276,42 +1284,42 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: url_launcher name: url_launcher
sha256: "75f2846facd11168d007529d6cd8fcb2b750186bea046af9711f10b907e1587e" sha256: eb1e00ab44303d50dd487aab67ebc575456c146c6af44422f9c13889984c00f3
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.1.10" version: "6.1.11"
url_launcher_android: url_launcher_android:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_android name: url_launcher_android
sha256: "1f4d9ebe86f333c15d318f81dcdc08b01d45da44af74552608455ebdc08d9732" sha256: "1a5848f598acc5b7d8f7c18b8cb834ab667e59a13edc3c93e9d09cf38cc6bc87"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.24" version: "6.0.34"
url_launcher_ios: url_launcher_ios:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_ios name: url_launcher_ios
sha256: c9cd648d2f7ab56968e049d4e9116f96a85517f1dd806b96a86ea1018a3a82e5 sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.1.1" version: "6.1.4"
url_launcher_linux: url_launcher_linux:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_linux name: url_launcher_linux
sha256: e29039160ab3730e42f3d811dc2a6d5f2864b90a70fb765ea60144b03307f682 sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.3" version: "3.0.5"
url_launcher_macos: url_launcher_macos:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_macos name: url_launcher_macos
sha256: "2dddb3291a57b074dade66b5e07e64401dd2487caefd4e9e2f467138d8c7eb06" sha256: "91ee3e75ea9dadf38036200c5d3743518f4a5eb77a8d13fda1ee5764373f185e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.3" version: "3.0.5"
url_launcher_platform_interface: url_launcher_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -1324,18 +1332,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_web name: url_launcher_web
sha256: "574cfbe2390666003c3a1d129bdc4574aaa6728f0c00a4829a81c316de69dd9b" sha256: "81fe91b6c4f84f222d186a9d23c73157dc4c8e1c71489c4d08be1ad3b228f1aa"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.15" version: "2.0.16"
url_launcher_windows: url_launcher_windows:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_windows name: url_launcher_windows
sha256: "97c9067950a0d09cbd93e2e3f0383d1403989362b97102fbf446473a48079a4b" sha256: "254708f17f7c20a9c8c471f67d86d76d4a3f9c1591aad1e15292008aceb82771"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.4" version: "3.0.6"
uuid: uuid:
dependency: transitive dependency: transitive
description: description:
@ -1356,42 +1364,42 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: video_player name: video_player
sha256: "6cec15c21974282994577ffcfb5b42e64a699d38583138ec8dcb3d0a6902a41c" sha256: de95f0e9405f29b5582573d4166132e71f83b3158aac14e8ee5767a54f4f1fbd
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.5.2" version: "2.6.1"
video_player_android: video_player_android:
dependency: transitive dependency: transitive
description: description:
name: video_player_android name: video_player_android
sha256: "0fc42778d794465f12456ccdade3e729e4339c8a112f9e58d170dc00f17b75f2" sha256: ae1c7d9a71c236a1bf9e567bd7ed4c90887e389a5f233b2192593f7f7395005c
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.11" version: "2.4.8"
video_player_avfoundation: video_player_avfoundation:
dependency: transitive dependency: transitive
description: description:
name: video_player_avfoundation name: video_player_avfoundation
sha256: "5df5411ff9d316f1dcbfee284e9838aa686e314f2a722b15c02cb7ce40ef9446" sha256: "4c274e439f349a0ee5cb3c42978393ede173a443b98f50de6ffe6900eaa19216"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.9" version: "2.4.6"
video_player_platform_interface: video_player_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: video_player_platform_interface name: video_player_platform_interface
sha256: "72ba04ad0eff76123c6d782ac46621cb8be476a89c33c89173fce982b6ec049b" sha256: a8c4dcae2a7a6e7cc1d7f9808294d968eca1993af34a98e95b9bdfa959bec684
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.2" version: "6.1.0"
video_player_web: video_player_web:
dependency: transitive dependency: transitive
description: description:
name: video_player_web name: video_player_web
sha256: d635bb2834f2b14cfd52c7fc9307a95dffbe768d116dd6047a4ecbba203289c8 sha256: "44ce41424d104dfb7cf6982cc6b84af2b007a24d126406025bf40de5d481c74c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.14" version: "2.0.16"
vm_service: vm_service:
dependency: transitive dependency: transitive
description: description:
@ -1444,18 +1452,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: watcher name: watcher
sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.2" version: "1.1.0"
web_socket_channel: web_socket_channel:
dependency: transitive dependency: transitive
description: description:
name: web_socket_channel name: web_socket_channel
sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.0" version: "2.4.0"
webdriver: webdriver:
dependency: transitive dependency: transitive
description: description:
@ -1468,10 +1476,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: win32 name: win32
sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 sha256: a6f0236dbda0f63aa9a25ad1ff9a9d8a4eaaa5012da0dc59d21afdb1dc361ca4
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.3" version: "3.1.4"
wkt_parser: wkt_parser:
dependency: transitive dependency: transitive
description: description:
@ -1492,10 +1500,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: xml name: xml
sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.2.2" version: "6.3.0"
xxh3: xxh3:
dependency: transitive dependency: transitive
description: description:
@ -1508,10 +1516,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: yaml name: yaml
sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.1" version: "3.1.2"
sdks: sdks:
dart: ">=3.0.0-0 <4.0.0" dart: ">=3.0.0 <4.0.0"
flutter: ">=3.3.0" flutter: ">=3.3.0"