[fix]: run issues fixed
This commit is contained in:
@@ -179,7 +179,7 @@ class AppProvider extends ChangeNotifier {
|
||||
for (final entry in repo.apps.entries) {
|
||||
final packageName = entry.key;
|
||||
final app = entry.value;
|
||||
|
||||
|
||||
if (mergedApps.containsKey(packageName)) {
|
||||
// App already exists, add this repository to the available sources
|
||||
final existing = mergedApps[packageName]!;
|
||||
@@ -187,13 +187,13 @@ class AppProvider extends ChangeNotifier {
|
||||
name: repo.name,
|
||||
url: app.repositoryUrl,
|
||||
);
|
||||
|
||||
|
||||
// Add the new repository if it's not already in the list
|
||||
final availableRepos = existing.availableRepositories ?? [];
|
||||
if (!availableRepos.contains(repoSource)) {
|
||||
// Create new list with the additional repository
|
||||
final updatedRepos = [...availableRepos, repoSource];
|
||||
|
||||
|
||||
// Keep the existing app but update available repositories
|
||||
mergedApps[packageName] = existing.copyWith(
|
||||
availableRepositories: updatedRepos,
|
||||
@@ -203,10 +203,7 @@ class AppProvider extends ChangeNotifier {
|
||||
// First time seeing this app, add it with its repository as a source
|
||||
mergedApps[packageName] = app.copyWith(
|
||||
availableRepositories: [
|
||||
RepositorySource(
|
||||
name: repo.name,
|
||||
url: app.repositoryUrl,
|
||||
),
|
||||
RepositorySource(name: repo.name, url: app.repositoryUrl),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -255,12 +252,13 @@ class AppProvider extends ChangeNotifier {
|
||||
final availableReposList = <RepositorySource>[];
|
||||
if (app.repositoryUrl.isNotEmpty) {
|
||||
// Find the repo name for the original URL
|
||||
final originalRepo = enabledRepos.where((r) => r.url == app.repositoryUrl).firstOrNull;
|
||||
final originalRepo = enabledRepos
|
||||
.where((r) => r.url == app.repositoryUrl)
|
||||
.firstOrNull;
|
||||
if (originalRepo != null) {
|
||||
availableReposList.add(RepositorySource(
|
||||
name: originalRepo.name,
|
||||
url: app.repositoryUrl,
|
||||
));
|
||||
availableReposList.add(
|
||||
RepositorySource(name: originalRepo.name, url: app.repositoryUrl),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,19 +270,21 @@ class AppProvider extends ChangeNotifier {
|
||||
if (repo.url == app.repositoryUrl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// Try to find the app in this repository via database
|
||||
final results = await _apiService.searchAppsFromRepositoryUrl(
|
||||
app.packageName, // Use exact package name for lookup
|
||||
repo.url,
|
||||
);
|
||||
|
||||
|
||||
// If found in this repository, return the source
|
||||
if (results.any((a) => a.packageName == app.packageName)) {
|
||||
return RepositorySource(name: repo.name, url: repo.url);
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('Error checking repo ${repo.name} for ${app.packageName}: $e');
|
||||
debugPrint(
|
||||
'Error checking repo ${repo.name} for ${app.packageName}: $e',
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
@@ -570,8 +570,10 @@ class AppProvider extends ChangeNotifier {
|
||||
if (fdroidApp == null) continue;
|
||||
|
||||
// Get the latest version based on user's unstable preference
|
||||
final latestVersion = fdroidApp.getLatestVersion(includeUnstable: includeUnstable);
|
||||
|
||||
final latestVersion = fdroidApp.getLatestVersion(
|
||||
includeUnstable: includeUnstable,
|
||||
);
|
||||
|
||||
// Check if F-Droid app has a latest version
|
||||
if (latestVersion == null) continue;
|
||||
|
||||
@@ -582,7 +584,6 @@ class AppProvider extends ChangeNotifier {
|
||||
if (latestVersion.versionCode > installedApp.versionCode!) {
|
||||
updatableApps.add(fdroidApp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by app name for consistent ordering
|
||||
|
||||
@@ -92,7 +92,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
_themeMode = ThemeMode.values[themeIndex];
|
||||
}
|
||||
final themeStyleIndex =
|
||||
prefs.getInt(_themeStyleKey) ?? 0; // Default to Florid
|
||||
prefs.getInt(_themeStyleKey) ?? 1; // Default to Florid
|
||||
if (themeStyleIndex >= 0 && themeStyleIndex < ThemeStyle.values.length) {
|
||||
_themeStyle = ThemeStyle.values[themeStyleIndex];
|
||||
}
|
||||
|
||||
+306
-287
@@ -16,7 +16,6 @@ import '../models/fdroid_app.dart';
|
||||
import '../providers/app_provider.dart';
|
||||
import '../providers/download_provider.dart';
|
||||
import '../providers/repositories_provider.dart';
|
||||
import '../providers/settings_provider.dart';
|
||||
import '../services/izzy_stats_service.dart';
|
||||
|
||||
class AppDetailsScreen extends StatefulWidget {
|
||||
@@ -68,7 +67,7 @@ class _AppDetailsScreenState extends State<AppDetailsScreen> {
|
||||
builder: (context, snapshot) {
|
||||
// Use tracked repository if available, otherwise use app's default repository
|
||||
final defaultRepoUrl = snapshot.data ?? app.repositoryUrl;
|
||||
|
||||
|
||||
return AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
transitionBuilder: (child, animation) {
|
||||
@@ -319,18 +318,24 @@ class _AppDetailsScreenState extends State<AppDetailsScreen> {
|
||||
padding: const EdgeInsets.only(top: 4.0),
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
final trackedRepoSource = availableRepos.firstWhere(
|
||||
(r) => r.url == trackedRepo,
|
||||
orElse: () => RepositorySource(
|
||||
name: 'Unknown',
|
||||
url: trackedRepo,
|
||||
),
|
||||
);
|
||||
final trackedRepoSource = availableRepos
|
||||
.firstWhere(
|
||||
(r) => r.url == trackedRepo,
|
||||
orElse: () => RepositorySource(
|
||||
name: 'Unknown',
|
||||
url: trackedRepo,
|
||||
),
|
||||
);
|
||||
return Text(
|
||||
'Previously installed from: ${trackedRepoSource.name}',
|
||||
style: Theme.of(dialogContext).textTheme.bodySmall?.copyWith(
|
||||
color: Theme.of(dialogContext).colorScheme.primary,
|
||||
),
|
||||
style: Theme.of(dialogContext)
|
||||
.textTheme
|
||||
.bodySmall
|
||||
?.copyWith(
|
||||
color: Theme.of(
|
||||
dialogContext,
|
||||
).colorScheme.primary,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -345,10 +350,13 @@ class _AppDetailsScreenState extends State<AppDetailsScreen> {
|
||||
itemBuilder: (index) {
|
||||
final repo = availableRepos[index];
|
||||
final isPrimary = repo.url == app.repositoryUrl;
|
||||
final isTracked = trackedRepo != null && repo.url == trackedRepo;
|
||||
final isTracked =
|
||||
trackedRepo != null && repo.url == trackedRepo;
|
||||
return MListItemData(
|
||||
selected: isPrimary || isTracked,
|
||||
leading: (isPrimary || isTracked) ? Icon(Symbols.check) : null,
|
||||
leading: (isPrimary || isTracked)
|
||||
? Icon(Symbols.check)
|
||||
: null,
|
||||
title: repo.name,
|
||||
subtitle: isTracked ? 'Previously installed from here' : null,
|
||||
onTap: () {
|
||||
@@ -544,11 +552,13 @@ class _AppDetailsScreenState extends State<AppDetailsScreen> {
|
||||
children: [
|
||||
Consumer2<DownloadProvider, AppProvider>(
|
||||
builder: (context, downloadProvider, appProvider, child) {
|
||||
final version = appProvider.getLatestVersion(widget.app);
|
||||
final version = appProvider.getLatestVersion(
|
||||
widget.app,
|
||||
);
|
||||
if (version == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
|
||||
final isInstalled = appProvider.isAppInstalled(
|
||||
widget.app.packageName,
|
||||
);
|
||||
@@ -967,7 +977,8 @@ class _AppDetailsScreenState extends State<AppDetailsScreen> {
|
||||
),
|
||||
Builder(
|
||||
builder: (context) {
|
||||
final latestVersion = appProvider.getLatestVersion(widget.app);
|
||||
final latestVersion = appProvider
|
||||
.getLatestVersion(widget.app);
|
||||
if (latestVersion?.whatsNew != null &&
|
||||
latestVersion!.whatsNew!.isNotEmpty) {
|
||||
return ChangelogPreview(
|
||||
@@ -1096,7 +1107,9 @@ class _AppDetailsScreenState extends State<AppDetailsScreen> {
|
||||
// Version info
|
||||
Builder(
|
||||
builder: (context) {
|
||||
final latestVersion = appProvider.getLatestVersion(widget.app);
|
||||
final latestVersion = context
|
||||
.read<AppProvider>()
|
||||
.getLatestVersion(widget.app);
|
||||
if (latestVersion != null) {
|
||||
return _VersionInfoSection(
|
||||
version: latestVersion,
|
||||
@@ -1148,7 +1161,7 @@ class _DownloadSectionState extends State<_DownloadSection> {
|
||||
return Consumer<AppProvider>(
|
||||
builder: (context, appProvider, _) {
|
||||
final latestVersion = appProvider.getLatestVersion(widget.app);
|
||||
|
||||
|
||||
if (latestVersion == null) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
@@ -1189,251 +1202,257 @@ class _DownloadSectionState extends State<_DownloadSection> {
|
||||
);
|
||||
}
|
||||
|
||||
return Consumer2<DownloadProvider, AppProvider>(
|
||||
builder: (context, downloadProvider, appProvider, child) {
|
||||
final version = latestVersion;
|
||||
return Consumer2<DownloadProvider, AppProvider>(
|
||||
builder: (context, downloadProvider, appProvider, child) {
|
||||
final version = latestVersion;
|
||||
|
||||
// Check if ANY version of this app is downloading
|
||||
DownloadInfo? activeDownloadInfo;
|
||||
bool isDownloading = false;
|
||||
String downloadingVersionName = version.versionName;
|
||||
// Check if ANY version of this app is downloading
|
||||
DownloadInfo? activeDownloadInfo;
|
||||
bool isDownloading = false;
|
||||
String downloadingVersionName = version.versionName;
|
||||
|
||||
if (widget.app.packages != null) {
|
||||
for (var pkg in widget.app.packages!.values) {
|
||||
final info = downloadProvider.getDownloadInfo(
|
||||
widget.app.packageName,
|
||||
pkg.versionName,
|
||||
);
|
||||
if (info?.status == DownloadStatus.downloading) {
|
||||
activeDownloadInfo = info;
|
||||
isDownloading = true;
|
||||
downloadingVersionName = pkg.versionName;
|
||||
break;
|
||||
if (widget.app.packages != null) {
|
||||
for (var pkg in widget.app.packages!.values) {
|
||||
final info = downloadProvider.getDownloadInfo(
|
||||
widget.app.packageName,
|
||||
pkg.versionName,
|
||||
);
|
||||
if (info?.status == DownloadStatus.downloading) {
|
||||
activeDownloadInfo = info;
|
||||
isDownloading = true;
|
||||
downloadingVersionName = pkg.versionName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final progress = isDownloading
|
||||
? downloadProvider.getProgress(
|
||||
widget.app.packageName,
|
||||
downloadingVersionName,
|
||||
)
|
||||
: 0.0;
|
||||
final progress = isDownloading
|
||||
? downloadProvider.getProgress(
|
||||
widget.app.packageName,
|
||||
downloadingVersionName,
|
||||
)
|
||||
: 0.0;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 16.0,
|
||||
children: [
|
||||
if (isDownloading && activeDownloadInfo != null) ...[
|
||||
Column(
|
||||
spacing: 4.0,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 16.0,
|
||||
children: [
|
||||
if (isDownloading && activeDownloadInfo != null) ...[
|
||||
Column(
|
||||
spacing: 4.0,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Downloading... ${(progress * 100).toInt()}%',
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
).animate().fadeIn(
|
||||
duration: Duration(milliseconds: 300),
|
||||
),
|
||||
if (activeDownloadInfo.totalBytes > 0)
|
||||
Text(
|
||||
'${activeDownloadInfo.formattedBytesDownloaded} / ${activeDownloadInfo.formattedTotalBytes}',
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
)
|
||||
.animate()
|
||||
.fadeIn(duration: Duration(milliseconds: 300))
|
||||
.slideY(
|
||||
begin: 0.5,
|
||||
end: 0,
|
||||
duration: Duration(milliseconds: 300),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'Downloading... ${(progress * 100).toInt()}%',
|
||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
).animate().fadeIn(duration: Duration(milliseconds: 300)),
|
||||
if (activeDownloadInfo.totalBytes > 0)
|
||||
Text(
|
||||
'${activeDownloadInfo.formattedBytesDownloaded} / ${activeDownloadInfo.formattedTotalBytes}',
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
)
|
||||
.animate()
|
||||
.fadeIn(duration: Duration(milliseconds: 300))
|
||||
.slideY(
|
||||
begin: 0.5,
|
||||
end: 0,
|
||||
duration: Duration(milliseconds: 300),
|
||||
),
|
||||
activeDownloadInfo.formattedSpeed,
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
)
|
||||
.animate()
|
||||
.fadeIn(duration: Duration(milliseconds: 300))
|
||||
.slideY(
|
||||
begin: 0.5,
|
||||
end: 0,
|
||||
duration: Duration(milliseconds: 300),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
LinearProgressIndicator(value: progress, year2023: false)
|
||||
.animate()
|
||||
.fadeIn(duration: Duration(milliseconds: 300))
|
||||
.slideY(
|
||||
begin: 0.5,
|
||||
end: 0,
|
||||
duration: Duration(milliseconds: 300),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
activeDownloadInfo.formattedSpeed,
|
||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
)
|
||||
.animate()
|
||||
.fadeIn(duration: Duration(milliseconds: 300))
|
||||
.slideY(
|
||||
begin: 0.5,
|
||||
end: 0,
|
||||
duration: Duration(milliseconds: 300),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
LinearProgressIndicator(value: progress, year2023: false)
|
||||
.animate()
|
||||
.fadeIn(duration: Duration(milliseconds: 300))
|
||||
.slideY(
|
||||
begin: 0.5,
|
||||
end: 0,
|
||||
duration: Duration(milliseconds: 300),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 8,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Card.outlined(
|
||||
margin: EdgeInsets.zero,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 8,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 32,
|
||||
child: Icon(
|
||||
Symbols.download,
|
||||
size: 32,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
version.sizeString,
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 8,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Card.outlined(
|
||||
margin: EdgeInsets.zero,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 8,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 32,
|
||||
child: Icon(
|
||||
Symbols.download,
|
||||
size: 32,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
version.sizeString,
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Card.outlined(
|
||||
margin: EdgeInsets.zero,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 8,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 32,
|
||||
child: Icon(
|
||||
Symbols.code_rounded,
|
||||
size: 32,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
version.versionName,
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(
|
||||
Expanded(
|
||||
child: Card.outlined(
|
||||
margin: EdgeInsets.zero,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 8,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 32,
|
||||
child: Icon(
|
||||
Symbols.code_rounded,
|
||||
size: 32,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
version.versionName,
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.stats?.hasAny != true)
|
||||
Expanded(
|
||||
child: Card.outlined(
|
||||
margin: EdgeInsets.zero,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 8,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 32,
|
||||
child: Icon(
|
||||
Symbols.license_rounded,
|
||||
size: 32,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
widget.app.license,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.stats?.hasAny == true)
|
||||
Expanded(
|
||||
child: Card.outlined(
|
||||
margin: EdgeInsets.zero,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 8,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 32,
|
||||
child: Icon(
|
||||
Symbols.chart_data,
|
||||
size: 32,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
widget.stats!.last365Days != null
|
||||
? _formatCount(widget.stats!.last365Days!)
|
||||
: 'N/A',
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (widget.stats?.hasAny != true)
|
||||
Expanded(
|
||||
child: Card.outlined(
|
||||
margin: EdgeInsets.zero,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 8,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 32,
|
||||
child: Icon(
|
||||
Symbols.license_rounded,
|
||||
size: 32,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
widget.app.license,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.stats?.hasAny == true)
|
||||
Expanded(
|
||||
child: Card.outlined(
|
||||
margin: EdgeInsets.zero,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 8,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 32,
|
||||
child: Icon(
|
||||
Symbols.chart_data,
|
||||
size: 32,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
widget.stats!.last365Days != null
|
||||
? _formatCount(widget.stats!.last365Days!)
|
||||
: 'N/A',
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1626,7 +1645,7 @@ class _AppInfoSection extends StatelessWidget {
|
||||
return Consumer<AppProvider>(
|
||||
builder: (context, appProvider, _) {
|
||||
final latestVersion = appProvider.getLatestVersion(app);
|
||||
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -1642,60 +1661,60 @@ class _AppInfoSection extends StatelessWidget {
|
||||
subtitle: app.packageName,
|
||||
onTap: () {},
|
||||
),
|
||||
MListItemData(
|
||||
leading: Icon(
|
||||
Symbols.license_rounded,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
title: 'License',
|
||||
subtitle: app.license,
|
||||
onTap: () {},
|
||||
),
|
||||
if (app.added != null)
|
||||
MListItemData(
|
||||
leading: Icon(
|
||||
Symbols.add,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
MListItemData(
|
||||
leading: Icon(
|
||||
Symbols.license_rounded,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
title: 'License',
|
||||
subtitle: app.license,
|
||||
onTap: () {},
|
||||
),
|
||||
title: 'Added',
|
||||
subtitle: _formatDate(app.added!),
|
||||
onTap: () {},
|
||||
),
|
||||
if (app.added != null)
|
||||
MListItemData(
|
||||
leading: Icon(
|
||||
Symbols.update,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
title: 'Last Updated',
|
||||
subtitle: _formatDate(app.lastUpdated!),
|
||||
onTap: () {},
|
||||
),
|
||||
if (latestVersion?.permissions?.isNotEmpty == true)
|
||||
MListItemData(
|
||||
leading: Icon(
|
||||
Symbols.security,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
title: 'Permissions ',
|
||||
subtitle: '(${latestVersion!.permissions!.length})',
|
||||
suffix: Icon(Symbols.arrow_forward),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => PermissionsScreen(
|
||||
permissions: latestVersion.permissions!,
|
||||
appName: app.name,
|
||||
),
|
||||
if (app.added != null)
|
||||
MListItemData(
|
||||
leading: Icon(
|
||||
Symbols.add,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
title: 'Added',
|
||||
subtitle: _formatDate(app.added!),
|
||||
onTap: () {},
|
||||
),
|
||||
if (app.added != null)
|
||||
MListItemData(
|
||||
leading: Icon(
|
||||
Symbols.update,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
title: 'Last Updated',
|
||||
subtitle: _formatDate(app.lastUpdated!),
|
||||
onTap: () {},
|
||||
),
|
||||
if (latestVersion?.permissions?.isNotEmpty == true)
|
||||
MListItemData(
|
||||
leading: Icon(
|
||||
Symbols.security,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
title: 'Permissions ',
|
||||
subtitle: '(${latestVersion!.permissions!.length})',
|
||||
suffix: Icon(Symbols.arrow_forward),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => PermissionsScreen(
|
||||
permissions: latestVersion.permissions!,
|
||||
appName: app.name,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user