mirror of
https://github.com/localsend/localsend.git
synced 2026-05-19 06:16:21 -04:00
File diff suppressed because it is too large
Load Diff
@@ -22,11 +22,34 @@ class ApkPickerPage extends StatefulWidget {
|
||||
|
||||
class _ApkPickerPageState extends State<ApkPickerPage> with Refena {
|
||||
final _textController = TextEditingController();
|
||||
final List<Application> _selectedApps = [];
|
||||
|
||||
void _pickApp(Application app) {
|
||||
Future<void> _pickApp(Application app) async {
|
||||
await ref.redux(selectedSendingFilesProvider).dispatchAsync(AddFilesAction(
|
||||
files: [app],
|
||||
converter: CrossFileConverters.convertApplication,
|
||||
));
|
||||
|
||||
if (mounted) {
|
||||
context.pop();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _pickApps(List<Application> apps) async {
|
||||
// ignore: discarded_futures
|
||||
ref.redux(selectedSendingFilesProvider).dispatchAsync(AddFilesAction(files: [app], converter: CrossFileConverters.convertApplication));
|
||||
context.pop();
|
||||
|
||||
for (Application app in apps) {
|
||||
await ref
|
||||
.redux(selectedSendingFilesProvider)
|
||||
.dispatchAsync(AddFilesAction(
|
||||
files: [app],
|
||||
converter: CrossFileConverters.convertApplication,
|
||||
));
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
context.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -36,6 +59,16 @@ class _ApkPickerPageState extends State<ApkPickerPage> with Refena {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _appSelection(Application app) {
|
||||
setState(() {
|
||||
if (_selectedApps.contains(app)) {
|
||||
_selectedApps.remove(app);
|
||||
} else {
|
||||
_selectedApps.add(app);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final apkParams = ref.watch(apkSearchParamProvider);
|
||||
@@ -61,15 +94,32 @@ class _ApkPickerPageState extends State<ApkPickerPage> with Refena {
|
||||
}, onSelected: (value) {
|
||||
switch (value) {
|
||||
case 0:
|
||||
ref.notifier(apkSearchParamProvider).setState((old) => old.copyWith(includeSystemApps: !old.includeSystemApps));
|
||||
ref.notifier(apkSearchParamProvider).setState((old) =>
|
||||
old.copyWith(includeSystemApps: !old.includeSystemApps));
|
||||
break;
|
||||
case 1:
|
||||
ref.notifier(apkSearchParamProvider).setState((old) => old.copyWith(onlyAppsWithLaunchIntent: !old.onlyAppsWithLaunchIntent));
|
||||
ref.notifier(apkSearchParamProvider).setState((old) =>
|
||||
old.copyWith(
|
||||
onlyAppsWithLaunchIntent:
|
||||
!old.onlyAppsWithLaunchIntent));
|
||||
break;
|
||||
}
|
||||
}),
|
||||
],
|
||||
),
|
||||
floatingActionButton: (_selectedApps.isEmpty)
|
||||
? Container()
|
||||
: FloatingActionButton.extended(
|
||||
onPressed: () async => await _pickApps(_selectedApps),
|
||||
label: Row(
|
||||
children: [
|
||||
const Icon(Icons.add),
|
||||
const SizedBox(width: 5),
|
||||
Text(
|
||||
'Add ${_selectedApps.length} ${(_selectedApps.length == 1) ? "App" : "Apps"}'),
|
||||
],
|
||||
),
|
||||
),
|
||||
body: ResponsiveListView.single(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15),
|
||||
tabletPadding: const EdgeInsets.symmetric(horizontal: 15),
|
||||
@@ -86,7 +136,9 @@ class _ApkPickerPageState extends State<ApkPickerPage> with Refena {
|
||||
controller: _textController,
|
||||
autofocus: true,
|
||||
onChanged: (s) {
|
||||
ref.notifier(apkSearchParamProvider).setState((old) => old.copyWith(query: s));
|
||||
ref
|
||||
.notifier(apkSearchParamProvider)
|
||||
.setState((old) => old.copyWith(query: s));
|
||||
setState(() {});
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
@@ -99,7 +151,9 @@ class _ApkPickerPageState extends State<ApkPickerPage> with Refena {
|
||||
suffixIcon: apkParams.query.isNotEmpty
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
ref.notifier(apkSearchParamProvider).setState((old) => old.copyWith(query: ''));
|
||||
ref
|
||||
.notifier(apkSearchParamProvider)
|
||||
.setState((old) => old.copyWith(query: ''));
|
||||
_textController.clear();
|
||||
},
|
||||
icon: const Icon(Icons.clear),
|
||||
@@ -110,7 +164,33 @@ class _ApkPickerPageState extends State<ApkPickerPage> with Refena {
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: Text(t.apkPickerPage.apps(n: apkAsync.data?.length ?? 0)),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(t.apkPickerPage.apps(n: apkAsync.data?.length ?? 0)),
|
||||
const Spacer(),
|
||||
Row(
|
||||
children: [
|
||||
const Text('Select Multiple Apps'),
|
||||
const SizedBox(width: 5),
|
||||
Switch(
|
||||
value: apkParams.selectMultipleApps,
|
||||
onChanged: (bool newValue) {
|
||||
setState(() {
|
||||
apkParams.selectMultipleApps =
|
||||
!apkParams.selectMultipleApps;
|
||||
});
|
||||
},
|
||||
activeTrackColor: Theme.of(context).colorScheme.primary,
|
||||
activeColor: Theme.of(context).colorScheme.onPrimary,
|
||||
inactiveThumbColor:
|
||||
Theme.of(context).colorScheme.outline,
|
||||
inactiveTrackColor:
|
||||
Theme.of(context).colorScheme.surface,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SliverToBoxAdapter(
|
||||
child: SizedBox(height: 10),
|
||||
@@ -127,7 +207,9 @@ class _ApkPickerPageState extends State<ApkPickerPage> with Refena {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: InkWell(
|
||||
onTap: () => _pickApp(app),
|
||||
onTap: () async => (apkParams.selectMultipleApps)
|
||||
? _appSelection(app)
|
||||
: _pickApp(app),
|
||||
customBorder: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
@@ -151,21 +233,28 @@ class _ApkPickerPageState extends State<ApkPickerPage> with Refena {
|
||||
),
|
||||
Consumer(
|
||||
builder: (context, ref) {
|
||||
final appSize = ref.watch(apkSizeProvider(app.apkFilePath));
|
||||
final appSize = ref.watch(
|
||||
apkSizeProvider(app.apkFilePath));
|
||||
final appSizeString = appSize.maybeWhen(
|
||||
data: (size) => '${size.asReadableFileSize} • ',
|
||||
data: (size) =>
|
||||
'${size.asReadableFileSize} • ',
|
||||
orElse: () => '',
|
||||
);
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'$appSizeString${app.versionName != null ? 'v${app.versionName}' : ''}',
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall,
|
||||
),
|
||||
Text(
|
||||
app.packageName,
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall,
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -174,6 +263,15 @@ class _ApkPickerPageState extends State<ApkPickerPage> with Refena {
|
||||
],
|
||||
),
|
||||
),
|
||||
if (apkParams.selectMultipleApps)
|
||||
Icon(
|
||||
_selectedApps.contains(app)
|
||||
? Icons.check_circle
|
||||
: Icons.radio_button_unchecked,
|
||||
color: _selectedApps.contains(app)
|
||||
? Theme.of(context).iconTheme.color
|
||||
: Colors.grey,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -194,7 +292,7 @@ class _ApkPickerPageState extends State<ApkPickerPage> with Refena {
|
||||
},
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(height: getNavBarPadding(context) + 30), // handle navigation bar + some additional padding
|
||||
child: SizedBox(height: getNavBarPadding(context) + 50),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -60,7 +60,9 @@ class _HomePageState extends State<HomePage> with Refena {
|
||||
super.initState();
|
||||
|
||||
ensureRef((ref) async {
|
||||
ref.redux(homePageControllerProvider).dispatch(ChangeTabAction(widget.initialTab));
|
||||
ref
|
||||
.redux(homePageControllerProvider)
|
||||
.dispatch(ChangeTabAction(widget.initialTab));
|
||||
await postInit(context, ref, widget.appStart);
|
||||
});
|
||||
}
|
||||
@@ -82,12 +84,17 @@ class _HomePageState extends State<HomePage> with Refena {
|
||||
});
|
||||
},
|
||||
onDragDone: (event) async {
|
||||
if (event.files.length == 1 && Directory(event.files.first.path).existsSync()) {
|
||||
if (event.files.length == 1 &&
|
||||
Directory(event.files.first.path).existsSync()) {
|
||||
// user dropped a directory
|
||||
await ref.redux(selectedSendingFilesProvider).dispatchAsync(AddDirectoryAction(event.files.first.path));
|
||||
await ref
|
||||
.redux(selectedSendingFilesProvider)
|
||||
.dispatchAsync(AddDirectoryAction(event.files.first.path));
|
||||
} else {
|
||||
// user dropped one or more files
|
||||
await ref.redux(selectedSendingFilesProvider).dispatchAsync(AddFilesAction(
|
||||
await ref
|
||||
.redux(selectedSendingFilesProvider)
|
||||
.dispatchAsync(AddFilesAction(
|
||||
files: event.files,
|
||||
converter: CrossFileConverters.convertXFile,
|
||||
));
|
||||
@@ -102,7 +109,9 @@ class _HomePageState extends State<HomePage> with Refena {
|
||||
if (!sizingInformation.isMobile)
|
||||
NavigationRail(
|
||||
selectedIndex: vm.currentTab.index,
|
||||
onDestinationSelected: (index) => vm.changeTab(HomeTab.values[index]),
|
||||
groupAlignment: 0,
|
||||
onDestinationSelected: (index) =>
|
||||
vm.changeTab(HomeTab.values[index]),
|
||||
extended: sizingInformation.isDesktop,
|
||||
backgroundColor: Theme.of(context).cardColorWithElevation,
|
||||
leading: sizingInformation.isDesktop
|
||||
@@ -111,7 +120,8 @@ class _HomePageState extends State<HomePage> with Refena {
|
||||
SizedBox(height: 20),
|
||||
Text(
|
||||
'LocalSend',
|
||||
style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
|
||||
style: TextStyle(
|
||||
fontSize: 32, fontWeight: FontWeight.bold),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
@@ -150,7 +160,9 @@ class _HomePageState extends State<HomePage> with Refena {
|
||||
children: [
|
||||
const Icon(Icons.file_download, size: 128),
|
||||
const SizedBox(height: 30),
|
||||
Text(t.sendTab.placeItems, style: Theme.of(context).textTheme.titleLarge),
|
||||
Text(t.sendTab.placeItems,
|
||||
style:
|
||||
Theme.of(context).textTheme.titleLarge),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -163,9 +175,11 @@ class _HomePageState extends State<HomePage> with Refena {
|
||||
bottomNavigationBar: sizingInformation.isMobile
|
||||
? NavigationBar(
|
||||
selectedIndex: vm.currentTab.index,
|
||||
onDestinationSelected: (index) => vm.changeTab(HomeTab.values[index]),
|
||||
onDestinationSelected: (index) =>
|
||||
vm.changeTab(HomeTab.values[index]),
|
||||
destinations: HomeTab.values.map((tab) {
|
||||
return NavigationDestination(icon: Icon(tab.icon), label: tab.label);
|
||||
return NavigationDestination(
|
||||
icon: Icon(tab.icon), label: tab.label);
|
||||
}).toList(),
|
||||
)
|
||||
: null,
|
||||
|
||||
@@ -44,10 +44,14 @@ class SendTab extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return ViewModelBuilder(
|
||||
provider: sendTabVmProvider,
|
||||
init: (context) => context.global.dispatchAsync(SendTabInitAction(context)), // ignore: discarded_futures
|
||||
init: (context) async => context.global.dispatchAsync(
|
||||
SendTabInitAction(context)), // ignore: discarded_futures
|
||||
builder: (context, vm) {
|
||||
final sizingInformation = SizingInformation(MediaQuery.sizeOf(context).width);
|
||||
final buttonWidth = sizingInformation.isDesktop ? BigButton.desktopWidth : BigButton.mobileWidth;
|
||||
final sizingInformation =
|
||||
SizingInformation(MediaQuery.sizeOf(context).width);
|
||||
final buttonWidth = sizingInformation.isDesktop
|
||||
? BigButton.desktopWidth
|
||||
: BigButton.mobileWidth;
|
||||
final ref = context.ref;
|
||||
return ResponsiveListView(
|
||||
padding: EdgeInsets.zero,
|
||||
@@ -55,7 +59,8 @@ class SendTab extends StatelessWidget {
|
||||
const SizedBox(height: 20),
|
||||
if (vm.selectedFiles.isEmpty) ...[
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: _horizontalPadding),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: _horizontalPadding),
|
||||
child: Text(
|
||||
t.sendTab.selection.title,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
@@ -80,9 +85,13 @@ class SendTab extends StatelessWidget {
|
||||
),
|
||||
] else ...[
|
||||
Card(
|
||||
margin: const EdgeInsets.only(bottom: 10, left: _horizontalPadding, right: _horizontalPadding),
|
||||
margin: const EdgeInsets.only(
|
||||
bottom: 10,
|
||||
left: _horizontalPadding,
|
||||
right: _horizontalPadding),
|
||||
child: Padding(
|
||||
padding: const EdgeInsetsDirectional.only(start: 15, top: 5, bottom: 15),
|
||||
padding: const EdgeInsetsDirectional.only(
|
||||
start: 15, top: 5, bottom: 15),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -94,15 +103,22 @@ class SendTab extends StatelessWidget {
|
||||
),
|
||||
const Spacer(),
|
||||
CustomIconButton(
|
||||
onPressed: () => ref.redux(selectedSendingFilesProvider).dispatch(ClearSelectionAction()),
|
||||
child: Icon(Icons.close, color: Theme.of(context).colorScheme.secondary),
|
||||
onPressed: () => ref
|
||||
.redux(selectedSendingFilesProvider)
|
||||
.dispatch(ClearSelectionAction()),
|
||||
child: Icon(Icons.close,
|
||||
color: Theme.of(context).colorScheme.secondary),
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(t.sendTab.selection.files(files: vm.selectedFiles.length)),
|
||||
Text(t.sendTab.selection.size(size: vm.selectedFiles.fold(0, (prev, curr) => prev + curr.size).asReadableFileSize)),
|
||||
Text(t.sendTab.selection
|
||||
.files(files: vm.selectedFiles.length)),
|
||||
Text(t.sendTab.selection.size(
|
||||
size: vm.selectedFiles
|
||||
.fold(0, (prev, curr) => prev + curr.size)
|
||||
.asReadableFileSize)),
|
||||
const SizedBox(height: 10),
|
||||
SizedBox(
|
||||
height: defaultThumbnailSize,
|
||||
@@ -124,18 +140,22 @@ class SendTab extends StatelessWidget {
|
||||
children: [
|
||||
TextButton(
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: Theme.of(context).colorScheme.onSurface,
|
||||
foregroundColor:
|
||||
Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
onPressed: () async {
|
||||
await context.push(() => const SelectedFilesPage());
|
||||
await context
|
||||
.push(() => const SelectedFilesPage());
|
||||
},
|
||||
child: Text(t.general.edit),
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
ElevatedButton.icon(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
foregroundColor: Theme.of(context).colorScheme.onPrimary,
|
||||
backgroundColor:
|
||||
Theme.of(context).colorScheme.primary,
|
||||
foregroundColor:
|
||||
Theme.of(context).colorScheme.onPrimary,
|
||||
),
|
||||
onPressed: () async {
|
||||
if (_options.length == 1) {
|
||||
@@ -168,7 +188,8 @@ class SendTab extends StatelessWidget {
|
||||
Flexible(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Text(t.sendTab.nearbyDevices, style: Theme.of(context).textTheme.titleMedium),
|
||||
child: Text(t.sendTab.nearbyDevices,
|
||||
style: Theme.of(context).textTheme.titleMedium),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
@@ -196,7 +217,10 @@ class SendTab extends StatelessWidget {
|
||||
),
|
||||
if (vm.nearbyDevices.isEmpty)
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(bottom: 10, left: _horizontalPadding, right: _horizontalPadding),
|
||||
padding: EdgeInsets.only(
|
||||
bottom: 10,
|
||||
left: _horizontalPadding,
|
||||
right: _horizontalPadding),
|
||||
child: Opacity(
|
||||
opacity: 0.3,
|
||||
child: DevicePlaceholderListTile(),
|
||||
@@ -205,7 +229,10 @@ class SendTab extends StatelessWidget {
|
||||
...vm.nearbyDevices.map((device) {
|
||||
final favoriteEntry = vm.favoriteDevices.findDevice(device);
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10, left: _horizontalPadding, right: _horizontalPadding),
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: 10,
|
||||
left: _horizontalPadding,
|
||||
right: _horizontalPadding),
|
||||
child: Hero(
|
||||
tag: 'device-${device.ip}',
|
||||
child: vm.sendMode == SendMode.multiple
|
||||
@@ -219,8 +246,10 @@ class SendTab extends StatelessWidget {
|
||||
device: device,
|
||||
isFavorite: favoriteEntry != null,
|
||||
nameOverride: favoriteEntry?.alias,
|
||||
onFavoriteTap: () async => await vm.onToggleFavorite(context, device),
|
||||
onTap: () async => await vm.onTapDevice(context, device),
|
||||
onFavoriteTap: () async =>
|
||||
await vm.onToggleFavorite(context, device),
|
||||
onTap: () async =>
|
||||
await vm.onTapDevice(context, device),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -236,7 +265,8 @@ class SendTab extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: _horizontalPadding),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: _horizontalPadding),
|
||||
child: Consumer(
|
||||
builder: (context, ref) {
|
||||
final animations = ref.watch(animationProvider);
|
||||
@@ -244,9 +274,13 @@ class SendTab extends StatelessWidget {
|
||||
durationMillis: 6000,
|
||||
running: animations,
|
||||
children: [
|
||||
Text(t.sendTab.help, style: const TextStyle(color: Colors.grey), textAlign: TextAlign.center),
|
||||
Text(t.sendTab.help,
|
||||
style: const TextStyle(color: Colors.grey),
|
||||
textAlign: TextAlign.center),
|
||||
if (checkPlatformCanReceiveShareIntent())
|
||||
Text(t.sendTab.shareIntentInfo, style: const TextStyle(color: Colors.grey), textAlign: TextAlign.center),
|
||||
Text(t.sendTab.shareIntentInfo,
|
||||
style: const TextStyle(color: Colors.grey),
|
||||
textAlign: TextAlign.center),
|
||||
],
|
||||
);
|
||||
},
|
||||
@@ -284,7 +318,9 @@ class _CircularPopupButton<T> extends StatelessWidget {
|
||||
type: MaterialType.transparency,
|
||||
child: DividerTheme(
|
||||
data: DividerThemeData(
|
||||
color: Theme.of(context).brightness == Brightness.light ? Colors.teal.shade100 : Colors.grey.shade700,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? Colors.teal.shade100
|
||||
: Colors.grey.shade700,
|
||||
),
|
||||
child: PopupMenuButton(
|
||||
offset: const Offset(0, 40),
|
||||
@@ -309,11 +345,16 @@ class _ScanButton extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final (scanningFavorites, scanningIps) = context.ref.watch(nearbyDevicesProvider.select((s) => (s.runningFavoriteScan, s.runningIps)));
|
||||
final (scanningFavorites, scanningIps) = context.ref.watch(
|
||||
nearbyDevicesProvider
|
||||
.select((s) => (s.runningFavoriteScan, s.runningIps)));
|
||||
final animations = context.ref.watch(animationProvider);
|
||||
|
||||
final spinning = (scanningFavorites || scanningIps.isNotEmpty) && animations;
|
||||
final iconColor = !animations && scanningIps.isNotEmpty ? Theme.of(context).colorScheme.warning : null;
|
||||
final spinning =
|
||||
(scanningFavorites || scanningIps.isNotEmpty) && animations;
|
||||
final iconColor = !animations && scanningIps.isNotEmpty
|
||||
? Theme.of(context).colorScheme.warning
|
||||
: null;
|
||||
|
||||
if (ips.length <= StartSmartScan.maxInterfaces) {
|
||||
return Tooltip(
|
||||
@@ -324,8 +365,11 @@ class _ScanButton extends StatelessWidget {
|
||||
reverse: true,
|
||||
child: CustomIconButton(
|
||||
onPressed: () async {
|
||||
context.redux(nearbyDevicesProvider).dispatch(ClearFoundDevicesAction());
|
||||
await context.global.dispatchAsync(StartSmartScan(forceLegacy: true));
|
||||
context
|
||||
.redux(nearbyDevicesProvider)
|
||||
.dispatch(ClearFoundDevicesAction());
|
||||
await context.global
|
||||
.dispatchAsync(StartSmartScan(forceLegacy: true));
|
||||
},
|
||||
child: Icon(Icons.sync, color: iconColor),
|
||||
),
|
||||
@@ -336,8 +380,11 @@ class _ScanButton extends StatelessWidget {
|
||||
return _CircularPopupButton(
|
||||
tooltip: t.sendTab.scan,
|
||||
onSelected: (ip) async {
|
||||
context.redux(nearbyDevicesProvider).dispatch(ClearFoundDevicesAction());
|
||||
await context.global.dispatchAsync(StartLegacySubnetScan(subnets: [ip]));
|
||||
context
|
||||
.redux(nearbyDevicesProvider)
|
||||
.dispatch(ClearFoundDevicesAction());
|
||||
await context.global
|
||||
.dispatchAsync(StartLegacySubnetScan(subnets: [ip]));
|
||||
},
|
||||
itemBuilder: (_) {
|
||||
return [
|
||||
@@ -378,7 +425,8 @@ class _RotatingSyncIcon extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scanningIps = context.ref.watch(nearbyDevicesProvider.select((s) => s.runningIps));
|
||||
final scanningIps =
|
||||
context.ref.watch(nearbyDevicesProvider.select((s) => s.runningIps));
|
||||
return RotatingWidget(
|
||||
duration: const Duration(seconds: 2),
|
||||
spinning: scanningIps.contains(ip),
|
||||
@@ -409,7 +457,8 @@ class _SendModeButton extends StatelessWidget {
|
||||
onSelect(SendMode.link);
|
||||
break;
|
||||
case -1:
|
||||
await showDialog(context: context, builder: (_) => const SendModeHelpDialog());
|
||||
await showDialog(
|
||||
context: context, builder: (_) => const SendModeHelpDialog());
|
||||
break;
|
||||
}
|
||||
},
|
||||
@@ -421,7 +470,8 @@ class _SendModeButton extends StatelessWidget {
|
||||
children: [
|
||||
Consumer(
|
||||
builder: (context, ref) {
|
||||
final sendMode = ref.watch(settingsProvider.select((s) => s.sendMode));
|
||||
final sendMode =
|
||||
ref.watch(settingsProvider.select((s) => s.sendMode));
|
||||
return Visibility(
|
||||
visible: sendMode == SendMode.single,
|
||||
maintainSize: true,
|
||||
@@ -443,7 +493,8 @@ class _SendModeButton extends StatelessWidget {
|
||||
children: [
|
||||
Consumer(
|
||||
builder: (context, ref) {
|
||||
final sendMode = ref.watch(settingsProvider.select((s) => s.sendMode));
|
||||
final sendMode =
|
||||
ref.watch(settingsProvider.select((s) => s.sendMode));
|
||||
return Visibility(
|
||||
visible: sendMode == SendMode.multiple,
|
||||
maintainSize: true,
|
||||
@@ -516,14 +567,24 @@ class _MultiSendDeviceListTile extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final ref = context.ref;
|
||||
final session = ref.watch(sendProvider).values.firstWhereOrNull((s) => s.target.ip == device.ip);
|
||||
final session = ref
|
||||
.watch(sendProvider)
|
||||
.values
|
||||
.firstWhereOrNull((s) => s.target.ip == device.ip);
|
||||
final double? progress;
|
||||
if (session != null) {
|
||||
final files = session.files.values.where((f) => f.token != null);
|
||||
final progressNotifier = ref.watch(progressProvider);
|
||||
final currBytes = files.fold<int>(
|
||||
0, (prev, curr) => prev + ((progressNotifier.getProgress(sessionId: session.sessionId, fileId: curr.file.id) * curr.file.size).round()));
|
||||
final totalBytes = files.fold<int>(0, (prev, curr) => prev + curr.file.size);
|
||||
0,
|
||||
(prev, curr) =>
|
||||
prev +
|
||||
((progressNotifier.getProgress(
|
||||
sessionId: session.sessionId, fileId: curr.file.id) *
|
||||
curr.file.size)
|
||||
.round()));
|
||||
final totalBytes =
|
||||
files.fold<int>(0, (prev, curr) => prev + curr.file.size);
|
||||
progress = totalBytes == 0 ? 0 : currBytes / totalBytes;
|
||||
} else {
|
||||
progress = null;
|
||||
|
||||
@@ -6,10 +6,11 @@ import 'package:localsend_app/provider/param/cached_apk_provider_param.dart';
|
||||
import 'package:refena_flutter/refena_flutter.dart';
|
||||
|
||||
final apkSearchParamProvider = StateProvider<ApkProviderParam>(
|
||||
(ref) => const ApkProviderParam(
|
||||
(ref) => ApkProviderParam(
|
||||
query: '',
|
||||
includeSystemApps: false,
|
||||
onlyAppsWithLaunchIntent: true,
|
||||
selectMultipleApps: false,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -20,12 +21,17 @@ final apkProvider = ViewProvider<AsyncValue<List<Application>>>((ref) {
|
||||
.watch(_apkProvider(CachedApkProviderParam(
|
||||
includeSystemApps: param.includeSystemApps,
|
||||
onlyAppsWithLaunchIntent: param.onlyAppsWithLaunchIntent,
|
||||
selectMultipleApps: param.selectMultipleApps,
|
||||
)))
|
||||
.maybeWhen(
|
||||
data: (apps) {
|
||||
final query = param.query.trim().toLowerCase();
|
||||
if (query.isNotEmpty) {
|
||||
apps = apps.where((a) => a.appName.toLowerCase().contains(query) || a.packageName.contains(query)).toList();
|
||||
apps = apps
|
||||
.where((a) =>
|
||||
a.appName.toLowerCase().contains(query) ||
|
||||
a.packageName.contains(query))
|
||||
.toList();
|
||||
}
|
||||
|
||||
apps.sort((a, b) => a.appName.compareTo(b.appName));
|
||||
@@ -40,7 +46,8 @@ final apkSizeProvider = FutureFamilyProvider<int, String>((_, path) {
|
||||
});
|
||||
|
||||
/// Provides a list of APKs which is cached
|
||||
final _apkProvider = FutureFamilyProvider<List<Application>, CachedApkProviderParam>((_, param) {
|
||||
final _apkProvider =
|
||||
FutureFamilyProvider<List<Application>, CachedApkProviderParam>((_, param) {
|
||||
return DeviceApps.getInstalledApplications(
|
||||
includeSystemApps: param.includeSystemApps,
|
||||
onlyAppsWithLaunchIntent: param.onlyAppsWithLaunchIntent,
|
||||
|
||||
@@ -7,10 +7,12 @@ class ApkProviderParam with ApkProviderParamMappable {
|
||||
final String query;
|
||||
final bool includeSystemApps;
|
||||
final bool onlyAppsWithLaunchIntent;
|
||||
bool selectMultipleApps;
|
||||
|
||||
const ApkProviderParam({
|
||||
ApkProviderParam({
|
||||
required this.query,
|
||||
required this.includeSystemApps,
|
||||
required this.onlyAppsWithLaunchIntent,
|
||||
this.selectMultipleApps = false,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -21,11 +21,15 @@ class ApkProviderParamMapper extends ClassMapperBase<ApkProviderParam> {
|
||||
final String id = 'ApkProviderParam';
|
||||
|
||||
static String _$query(ApkProviderParam v) => v.query;
|
||||
static const Field<ApkProviderParam, String> _f$query = Field('query', _$query);
|
||||
static const Field<ApkProviderParam, String> _f$query =
|
||||
Field('query', _$query);
|
||||
static bool _$includeSystemApps(ApkProviderParam v) => v.includeSystemApps;
|
||||
static const Field<ApkProviderParam, bool> _f$includeSystemApps = Field('includeSystemApps', _$includeSystemApps);
|
||||
static bool _$onlyAppsWithLaunchIntent(ApkProviderParam v) => v.onlyAppsWithLaunchIntent;
|
||||
static const Field<ApkProviderParam, bool> _f$onlyAppsWithLaunchIntent = Field('onlyAppsWithLaunchIntent', _$onlyAppsWithLaunchIntent);
|
||||
static const Field<ApkProviderParam, bool> _f$includeSystemApps =
|
||||
Field('includeSystemApps', _$includeSystemApps);
|
||||
static bool _$onlyAppsWithLaunchIntent(ApkProviderParam v) =>
|
||||
v.onlyAppsWithLaunchIntent;
|
||||
static const Field<ApkProviderParam, bool> _f$onlyAppsWithLaunchIntent =
|
||||
Field('onlyAppsWithLaunchIntent', _$onlyAppsWithLaunchIntent);
|
||||
|
||||
@override
|
||||
final MappableFields<ApkProviderParam> fields = const {
|
||||
@@ -36,9 +40,10 @@ class ApkProviderParamMapper extends ClassMapperBase<ApkProviderParam> {
|
||||
|
||||
static ApkProviderParam _instantiate(DecodingData data) {
|
||||
return ApkProviderParam(
|
||||
query: data.dec(_f$query),
|
||||
includeSystemApps: data.dec(_f$includeSystemApps),
|
||||
onlyAppsWithLaunchIntent: data.dec(_f$onlyAppsWithLaunchIntent));
|
||||
query: data.dec(_f$query),
|
||||
includeSystemApps: data.dec(_f$includeSystemApps),
|
||||
onlyAppsWithLaunchIntent: data.dec(_f$onlyAppsWithLaunchIntent),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -55,58 +60,81 @@ class ApkProviderParamMapper extends ClassMapperBase<ApkProviderParam> {
|
||||
|
||||
mixin ApkProviderParamMappable {
|
||||
String serialize() {
|
||||
return ApkProviderParamMapper.ensureInitialized().encodeJson<ApkProviderParam>(this as ApkProviderParam);
|
||||
return ApkProviderParamMapper.ensureInitialized()
|
||||
.encodeJson<ApkProviderParam>(this as ApkProviderParam);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return ApkProviderParamMapper.ensureInitialized().encodeMap<ApkProviderParam>(this as ApkProviderParam);
|
||||
return ApkProviderParamMapper.ensureInitialized()
|
||||
.encodeMap<ApkProviderParam>(this as ApkProviderParam);
|
||||
}
|
||||
|
||||
ApkProviderParamCopyWith<ApkProviderParam, ApkProviderParam, ApkProviderParam> get copyWith =>
|
||||
_ApkProviderParamCopyWithImpl(this as ApkProviderParam, $identity, $identity);
|
||||
ApkProviderParamCopyWith<ApkProviderParam, ApkProviderParam, ApkProviderParam>
|
||||
get copyWith => _ApkProviderParamCopyWithImpl(
|
||||
this as ApkProviderParam, $identity, $identity);
|
||||
@override
|
||||
String toString() {
|
||||
return ApkProviderParamMapper.ensureInitialized().stringifyValue(this as ApkProviderParam);
|
||||
return ApkProviderParamMapper.ensureInitialized()
|
||||
.stringifyValue(this as ApkProviderParam);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return ApkProviderParamMapper.ensureInitialized().equalsValue(this as ApkProviderParam, other);
|
||||
return ApkProviderParamMapper.ensureInitialized()
|
||||
.equalsValue(this as ApkProviderParam, other);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return ApkProviderParamMapper.ensureInitialized().hashValue(this as ApkProviderParam);
|
||||
return ApkProviderParamMapper.ensureInitialized()
|
||||
.hashValue(this as ApkProviderParam);
|
||||
}
|
||||
}
|
||||
|
||||
extension ApkProviderParamValueCopy<$R, $Out> on ObjectCopyWith<$R, ApkProviderParam, $Out> {
|
||||
ApkProviderParamCopyWith<$R, ApkProviderParam, $Out> get $asApkProviderParam => $base.as((v, t, t2) => _ApkProviderParamCopyWithImpl(v, t, t2));
|
||||
extension ApkProviderParamValueCopy<$R, $Out>
|
||||
on ObjectCopyWith<$R, ApkProviderParam, $Out> {
|
||||
ApkProviderParamCopyWith<$R, ApkProviderParam, $Out>
|
||||
get $asApkProviderParam =>
|
||||
$base.as((v, t, t2) => _ApkProviderParamCopyWithImpl(v, t, t2));
|
||||
}
|
||||
|
||||
abstract class ApkProviderParamCopyWith<$R, $In extends ApkProviderParam, $Out> implements ClassCopyWith<$R, $In, $Out> {
|
||||
$R call({String? query, bool? includeSystemApps, bool? onlyAppsWithLaunchIntent});
|
||||
ApkProviderParamCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(Then<$Out2, $R2> t);
|
||||
abstract class ApkProviderParamCopyWith<$R, $In extends ApkProviderParam, $Out>
|
||||
implements ClassCopyWith<$R, $In, $Out> {
|
||||
$R call(
|
||||
{String? query, bool? includeSystemApps, bool? onlyAppsWithLaunchIntent});
|
||||
ApkProviderParamCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(
|
||||
Then<$Out2, $R2> t);
|
||||
}
|
||||
|
||||
class _ApkProviderParamCopyWithImpl<$R, $Out> extends ClassCopyWithBase<$R, ApkProviderParam, $Out>
|
||||
class _ApkProviderParamCopyWithImpl<$R, $Out>
|
||||
extends ClassCopyWithBase<$R, ApkProviderParam, $Out>
|
||||
implements ApkProviderParamCopyWith<$R, ApkProviderParam, $Out> {
|
||||
_ApkProviderParamCopyWithImpl(super.value, super.then, super.then2);
|
||||
|
||||
@override
|
||||
late final ClassMapperBase<ApkProviderParam> $mapper = ApkProviderParamMapper.ensureInitialized();
|
||||
late final ClassMapperBase<ApkProviderParam> $mapper =
|
||||
ApkProviderParamMapper.ensureInitialized();
|
||||
@override
|
||||
$R call({String? query, bool? includeSystemApps, bool? onlyAppsWithLaunchIntent}) => $apply(FieldCopyWithData({
|
||||
$R call(
|
||||
{String? query,
|
||||
bool? includeSystemApps,
|
||||
bool? onlyAppsWithLaunchIntent}) =>
|
||||
$apply(FieldCopyWithData({
|
||||
if (query != null) #query: query,
|
||||
if (includeSystemApps != null) #includeSystemApps: includeSystemApps,
|
||||
if (onlyAppsWithLaunchIntent != null) #onlyAppsWithLaunchIntent: onlyAppsWithLaunchIntent
|
||||
if (onlyAppsWithLaunchIntent != null)
|
||||
#onlyAppsWithLaunchIntent: onlyAppsWithLaunchIntent
|
||||
}));
|
||||
@override
|
||||
ApkProviderParam $make(CopyWithData data) => ApkProviderParam(
|
||||
query: data.get(#query, or: $value.query),
|
||||
includeSystemApps: data.get(#includeSystemApps, or: $value.includeSystemApps),
|
||||
onlyAppsWithLaunchIntent: data.get(#onlyAppsWithLaunchIntent, or: $value.onlyAppsWithLaunchIntent));
|
||||
includeSystemApps:
|
||||
data.get(#includeSystemApps, or: $value.includeSystemApps),
|
||||
onlyAppsWithLaunchIntent: data.get(#onlyAppsWithLaunchIntent,
|
||||
or: $value.onlyAppsWithLaunchIntent));
|
||||
|
||||
@override
|
||||
ApkProviderParamCopyWith<$R2, ApkProviderParam, $Out2> $chain<$R2, $Out2>(Then<$Out2, $R2> t) => _ApkProviderParamCopyWithImpl($value, $cast, t);
|
||||
ApkProviderParamCopyWith<$R2, ApkProviderParam, $Out2> $chain<$R2, $Out2>(
|
||||
Then<$Out2, $R2> t) =>
|
||||
_ApkProviderParamCopyWithImpl($value, $cast, t);
|
||||
}
|
||||
|
||||
@@ -6,9 +6,11 @@ part 'cached_apk_provider_param.mapper.dart';
|
||||
class CachedApkProviderParam with CachedApkProviderParamMappable {
|
||||
final bool includeSystemApps;
|
||||
final bool onlyAppsWithLaunchIntent;
|
||||
bool selectMultipleApps;
|
||||
|
||||
const CachedApkProviderParam({
|
||||
CachedApkProviderParam({
|
||||
required this.includeSystemApps,
|
||||
required this.onlyAppsWithLaunchIntent,
|
||||
this.selectMultipleApps = false,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -377,10 +377,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: extended_image
|
||||
sha256: "8ad4917eaae7271ce6d975d5c0040c7903010262908fbdb49ff2798fca754d3b"
|
||||
sha256: "69d4299043334ecece679996e47d0b0891cd8c29d8da0034868443506f1d9a78"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.3.0"
|
||||
version: "8.3.1"
|
||||
extended_image_library:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -433,34 +433,34 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_android
|
||||
sha256: b8c9717a0177ca6fa035554b82cd6c83b838ddc66b7704eb6df0f77f027ecc90
|
||||
sha256: "00aafa9ae05a8663d0b4f17abd2a02316911ca0f46f9b9dacb9578b324d99590"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.1+7"
|
||||
version: "0.5.1+9"
|
||||
file_selector_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_ios
|
||||
sha256: "38ebf91ecbcfa89a9639a0854ccaed8ab370c75678938eebca7d34184296f0bb"
|
||||
sha256: "94b98ad950b8d40d96fee8fa88640c2e4bd8afcdd4817993bd04e20310f45420"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.3"
|
||||
version: "0.5.3+1"
|
||||
file_selector_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_linux
|
||||
sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492"
|
||||
sha256: "712ce7fab537ba532c8febdb1a8f167b32441e74acd68c3ccb2e36dcb52c4ab2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.2+1"
|
||||
version: "0.9.3"
|
||||
file_selector_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_macos
|
||||
sha256: cb284e267f8e2a45a904b5c094d2ba51d0aabfc20b1538ab786d9ef7dc2bf75c
|
||||
sha256: "271ab9986df0c135d45c3cdb6bd0faa5db6f4976d3e4b437cf7d0f258d941bfc"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.4+1"
|
||||
version: "0.9.4+2"
|
||||
file_selector_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -481,10 +481,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_windows
|
||||
sha256: "2ad726953f6e8affbc4df8dc78b77c3b4a060967a291e528ef72ae846c60fb69"
|
||||
sha256: "8f5d2f6590d51ecd9179ba39c64f722edc15226cc93dcc8698466ad36a4a85a4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.3+2"
|
||||
version: "0.9.3+3"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -547,10 +547,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_plugin_android_lifecycle
|
||||
sha256: "9ee02950848f61c4129af3d6ec84a1cfc0e47931abc746b03e7a3bc3e8ff6eda"
|
||||
sha256: "9b78450b89f059e96c9ebb355fa6b3df1d6b330436e0b885fb49594c41721398"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.22"
|
||||
version: "2.0.23"
|
||||
flutter_test:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@@ -677,10 +677,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_android
|
||||
sha256: c0a6763d50b354793d0192afd0a12560b823147d3ded7c6b77daf658fa05cc85
|
||||
sha256: d3e5e00fdfeca8fd4ffb3227001264d449cc8950414c2ff70b0e06b9c628e643
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.12+13"
|
||||
version: "0.8.12+15"
|
||||
image_picker_for_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -733,10 +733,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_size_getter
|
||||
sha256: f98c4246144e9b968899d2dfde69091e22a539bb64bc9b0bea51505fbb490e57
|
||||
sha256: "0511799498340b70993d2dfb34b55a2247b5b801d75a6cdd4543acfcafdb12b0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
version: "2.2.0"
|
||||
in_app_purchase:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -749,10 +749,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: in_app_purchase_android
|
||||
sha256: "25eb8694819caca282a527c26d5a1775164965c554ee99b9c10f3a0e44675c75"
|
||||
sha256: bee60266e443d4ae0e4809bae7f9cd4d6be75ab5ec6bb3d2ca737774a274a3bd
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.6+8"
|
||||
version: "0.3.6+9"
|
||||
in_app_purchase_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1038,10 +1038,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: "6f01f8e37ec30b07bc424b4deabac37cacb1bc7e2e515ad74486039918a37eb7"
|
||||
sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.10"
|
||||
version: "2.2.12"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1327,18 +1327,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_android
|
||||
sha256: "480ba4345773f56acda9abf5f50bd966f581dac5d514e5fc4a18c62976bbba7e"
|
||||
sha256: "3b9febd815c9ca29c9e3520d50ec32f49157711e143b7a4ca039eb87e8ade5ab"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
version: "2.3.3"
|
||||
shared_preferences_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_foundation
|
||||
sha256: c4b35f6cb8f63c147312c054ce7c2254c8066745125264f0c88739c417fc9d9f
|
||||
sha256: "07e050c7cd39bad516f8d64c455f04508d09df104be326d8c02551590a0d513d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.2"
|
||||
version: "2.5.3"
|
||||
shared_preferences_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1628,10 +1628,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_android
|
||||
sha256: e35a698ac302dd68e41f73250bd9517fe3ab5fa4f18fe4647a0872db61bacbab
|
||||
sha256: "8fc3bae0b68c02c47c5c86fa8bfa74471d42687b0eded01b78de87872db745e2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.10"
|
||||
version: "6.3.12"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1716,34 +1716,34 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player
|
||||
sha256: e30df0d226c4ef82e2c150ebf6834b3522cf3f654d8e2f9419d376cdc071425d
|
||||
sha256: "4a8c3492d734f7c39c2588a3206707a05ee80cef52e8c7f3b2078d430c84bc17"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.9.1"
|
||||
version: "2.9.2"
|
||||
video_player_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_android
|
||||
sha256: "38d8fe136c427abdce68b5e8c3c08ea29d7a794b453c7a51b12ecfad4aad9437"
|
||||
sha256: ae5287ca367e206eb74d7b3dc1ce0b8912ab9a3fc0597b6a101a0a5239f229d3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.7.3"
|
||||
version: "2.7.9"
|
||||
video_player_avfoundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_avfoundation
|
||||
sha256: d1e9a824f2b324000dc8fb2dcb2a3285b6c1c7c487521c63306cc5b394f68a7c
|
||||
sha256: cd5ab8a8bc0eab65ab0cea40304097edc46da574c8c1ecdee96f28cd8ef3792f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.6.1"
|
||||
version: "2.6.2"
|
||||
video_player_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_platform_interface
|
||||
sha256: "236454725fafcacf98f0f39af0d7c7ab2ce84762e3b63f2cbb3ef9a7e0550bc6"
|
||||
sha256: "229d7642ccd9f3dc4aba169609dd6b5f3f443bb4cc15b82f7785fcada5af9bbb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.2"
|
||||
version: "6.2.3"
|
||||
video_player_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1836,10 +1836,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: "68d1e89a91ed61ad9c370f9f8b6effed9ae5e0ede22a270bdfa6daf79fc2290a"
|
||||
sha256: "4d45dc9069dba4619dc0ebd93c7cec5e66d8482cb625a370ac806dcc8165f2ec"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.5.4"
|
||||
version: "5.5.5"
|
||||
win32_registry:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -1868,10 +1868,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
|
||||
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
version: "1.1.0"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
115
cli/pubspec.lock
115
cli/pubspec.lock
@@ -5,18 +5,23 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051
|
||||
sha256: "45cfa8471b89fb6643fe9bf51bd7931a76b8f5ec2d65de4fb176dba8d4f22c77"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "64.0.0"
|
||||
version: "73.0.0"
|
||||
_macros:
|
||||
dependency: transitive
|
||||
description: dart
|
||||
source: sdk
|
||||
version: "0.3.2"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893"
|
||||
sha256: "4959fec185fe70cce007c57e9ab6983101dbe593d2bf8bbfb4453aaec0cf470a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.0"
|
||||
version: "6.8.0"
|
||||
args:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -45,10 +50,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.18.0"
|
||||
version: "1.19.0"
|
||||
common:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -68,18 +73,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: coverage
|
||||
sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097"
|
||||
sha256: c1fb2dce3c0085f39dc72668e85f8e0210ec7de05345821ff58530567df345a5
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.6.3"
|
||||
version: "1.9.2"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
||||
sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
version: "3.0.5"
|
||||
dart_mappable:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -116,10 +121,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: frontend_server_client
|
||||
sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612"
|
||||
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
version: "4.0.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -140,10 +145,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
|
||||
sha256: "40f592dd352890c3b60fec1b68e786cefb9603e05ff303dbc4dda49b304ecdf4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.2"
|
||||
version: "4.1.0"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -156,10 +161,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
||||
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.7"
|
||||
version: "0.7.1"
|
||||
lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
@@ -176,30 +181,38 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
macros:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: macros
|
||||
sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.2-main.4"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
|
||||
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.16"
|
||||
version: "0.12.16+1"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.12.0"
|
||||
version: "1.16.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mime
|
||||
sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
|
||||
sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
version: "1.0.6"
|
||||
node_preamble:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -244,18 +257,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: refena
|
||||
sha256: "04ef88e22bee3f6735a9e11d81f41c8cf00bd264c396214945156b9858b07619"
|
||||
sha256: "1446e9622451e0cffef2af5b3fd57a52f0688d7c9eb848e969c16ccc2d14e833"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
version: "2.1.1"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf
|
||||
sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
|
||||
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
version: "1.4.2"
|
||||
shelf_packages_handler:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -268,26 +281,26 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_static
|
||||
sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e
|
||||
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
version: "1.1.3"
|
||||
shelf_web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_web_socket
|
||||
sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1"
|
||||
sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
version: "2.0.0"
|
||||
source_map_stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_map_stack_trace
|
||||
sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae"
|
||||
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
source_maps:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -308,10 +321,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.1"
|
||||
version: "1.12.0"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -324,10 +337,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
|
||||
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.3.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -340,26 +353,26 @@ packages:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: test
|
||||
sha256: "9b0dd8e36af4a5b1569029949d50a52cb2a2a2fdaa20cebb96e6603b9ae241f9"
|
||||
sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.24.6"
|
||||
version: "1.25.8"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.1"
|
||||
version: "0.7.3"
|
||||
test_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_core
|
||||
sha256: "4bef837e56375537055fdbbbf6dd458b1859881f4c7e6da936158f77d61ab265"
|
||||
sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.6"
|
||||
version: "0.6.5"
|
||||
type_plus:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -380,10 +393,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583
|
||||
sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.10.0"
|
||||
version: "14.3.0"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -400,14 +413,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket
|
||||
sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.6"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
|
||||
sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
version: "3.0.1"
|
||||
webkit_inspection_protocol:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -425,4 +446,4 @@ packages:
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.1.1 <4.0.0"
|
||||
dart: ">=3.4.0 <4.0.0"
|
||||
|
||||
Reference in New Issue
Block a user