favorites, demoting

This commit is contained in:
randogoth 2025-02-24 22:04:57 +02:00
parent a88a61cf01
commit dacfc1d059

View file

@ -55,7 +55,9 @@ class AppInfo {
final String name;
final String packageName;
final List<String> tags;
DateTime? lastUsed; // New field to track last used time
DateTime? lastUsed;
bool isPinned;
bool isDemoted;
AppInfo({
this.icon,
@ -63,6 +65,8 @@ class AppInfo {
required this.packageName,
required this.tags,
this.lastUsed,
this.isPinned = false,
this.isDemoted = false,
});
}
@ -114,6 +118,9 @@ class _AppLauncherScreenState extends State<AppLauncherScreen> with WidgetsBindi
List<AppInfo> loadedApps = installedApps.map((app) {
final lastUsedMillis = SharedPreferencesService().getInt("lastUsed_${app.packageName}");
final storedTags = SharedPreferencesService().getString("tags_${app.packageName}");
final isPinned = SharedPreferencesService().getBool("isPinned_${app.packageName}", false);
final isDemoted = SharedPreferencesService().getBool("isDemoted_${app.packageName}", false);
List<String> tags = [];
if (storedTags != null && storedTags.trim().isNotEmpty) {
@ -131,6 +138,8 @@ class _AppLauncherScreenState extends State<AppLauncherScreen> with WidgetsBindi
packageName: app.packageName,
tags: tags,
lastUsed: lastUsedMillis != null ? DateTime.fromMillisecondsSinceEpoch(lastUsedMillis) : null,
isPinned: isPinned,
isDemoted: isDemoted,
);
}).toList();
@ -151,16 +160,22 @@ class _AppLauncherScreenState extends State<AppLauncherScreen> with WidgetsBindi
return matchesName || matchesTag;
}).toList();
if (context.read<AppSettings>().sortLastUsed) {
// Sort pinned apps first, then by last used or alphabetically, then demoted apps
filteredApps.sort((a, b) {
if (a.isPinned && !b.isPinned) return -1;
if (!a.isPinned && b.isPinned) return 1;
if (a.isDemoted && !b.isDemoted) return 1;
if (!a.isDemoted && b.isDemoted) return -1;
if (context.read<AppSettings>().sortLastUsed) {
DateTime aTime = a.lastUsed ?? DateTime.fromMillisecondsSinceEpoch(0);
DateTime bTime = b.lastUsed ?? DateTime.fromMillisecondsSinceEpoch(0);
return bTime.compareTo(aTime);
});
} else {
filteredApps.sort((a, b) => a.name.compareTo(b.name));
return a.name.compareTo(b.name);
}
});
});
}
Future<void> _launchApp(AppInfo app) async {
@ -197,6 +212,57 @@ class _AppLauncherScreenState extends State<AppLauncherScreen> with WidgetsBindi
}
}
void _showContextMenu(BuildContext context, AppInfo app) {
showModalBottomSheet(
context: context,
builder: (context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: Icon(app.isPinned ? Icons.push_pin : Icons.push_pin_outlined),
title: Text(app.isPinned ? 'Unpin' : 'Pin'),
onTap: () async {
Navigator.pop(context); // Close the menu
await _togglePin(app);
},
),
ListTile(
leading: Icon(app.isDemoted ? Icons.arrow_upward : Icons.arrow_downward),
title: Text(app.isDemoted ? 'Reset' : 'Demote'),
onTap: () async {
Navigator.pop(context); // Close the menu
await _toggleDemote(app);
},
),
],
);
},
);
}
Future<void> _togglePin(AppInfo app) async {
setState(() {
app.isPinned = !app.isPinned;
if (app.isPinned) {
app.isDemoted = false; // Cannot be pinned and demoted at the same time
}
});
await SharedPreferencesService().setBool("isPinned_${app.packageName}", app.isPinned);
_filterApps();
}
Future<void> _toggleDemote(AppInfo app) async {
setState(() {
app.isDemoted = !app.isDemoted;
if (app.isDemoted) {
app.isPinned = false; // Cannot be pinned and demoted at the same time
}
});
await SharedPreferencesService().setBool("isDemoted_${app.packageName}", app.isDemoted);
_filterApps();
}
void _editAppTags(AppInfo app) {
TextEditingController tagController = TextEditingController(text: app.tags.join(" "));
showDialog(
@ -303,6 +369,15 @@ class _AppLauncherScreenState extends State<AppLauncherScreen> with WidgetsBindi
);
}
Widget _buildTrailingIcon(AppInfo app) {
if (app.isPinned) {
return Icon(Icons.push_pin, color: Colors.grey); // Pin icon for pinned apps
} else if (app.isDemoted) {
return Icon(Icons.disabled_by_default_outlined, color: Colors.grey); // Demote icon for demoted apps
}
return SizedBox.shrink(); // No icon for normal apps
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -452,11 +527,13 @@ class _AppLauncherScreenState extends State<AppLauncherScreen> with WidgetsBindi
overflow: TextOverflow.ellipsis,
)
: null,
trailing: _buildTrailingIcon(app), // Add trailing icon
onTap: () => _launchApp(app),
onLongPress: () => _showContextMenu(context, app),
),
);
},
),
)
);
}
}