favorites, demoting
This commit is contained in:
parent
a88a61cf01
commit
dacfc1d059
1 changed files with 85 additions and 8 deletions
|
|
@ -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,15 +160,21 @@ class _AppLauncherScreenState extends State<AppLauncherScreen> with WidgetsBindi
|
|||
return matchesName || matchesTag;
|
||||
}).toList();
|
||||
|
||||
if (context.read<AppSettings>().sortLastUsed) {
|
||||
filteredApps.sort((a, b) {
|
||||
// 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));
|
||||
}
|
||||
} else {
|
||||
return a.name.compareTo(b.name);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -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),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue