Skip to content

Commit

Permalink
global sticker search
Browse files Browse the repository at this point in the history
sleddev committed Jan 16, 2025

Verified

This commit was signed with the committer’s verified signature.
sleddev Sled Dev
1 parent d414956 commit 1b0ed39
Showing 5 changed files with 183 additions and 69 deletions.
73 changes: 48 additions & 25 deletions lib/models/config_model.dart
Original file line number Diff line number Diff line change
@@ -6,26 +6,47 @@ class ConfigData {
bool alwaysOnTop;
int copySize;
bool showSearchBar;
bool globalSearch;
List<StickerPackConfig> stickerPacks;

ConfigData(this.token, this.alwaysOnTop, this.copySize, this.showSearchBar, this.stickerPacks,);
ConfigData(
this.token,
this.alwaysOnTop,
this.copySize,
this.showSearchBar,
this.globalSearch,
this.stickerPacks,
);

ConfigData.fromJson(Map<String, dynamic> json, Directory wd)
: token = json['token'] ?? '',
alwaysOnTop = json['always_on_top'] is bool ? json['always_on_top'] ?? true : true,
copySize = max(1, min(512, json['copy_size'] is int ? json['copy_size'] ?? 512 : 512)),
showSearchBar = json['show_search_bar'] is bool ? json['show_search_bar'] ?? true : true,
stickerPacks = List<StickerPackConfig>.generate(
((json['sticker_packs'] ?? []) as List<dynamic>).length,
(index) => StickerPackConfig.fromJson(((json['sticker_packs'] ?? []) as List<dynamic>)[index], wd));
: token = json['token'] ?? '',
alwaysOnTop = json['always_on_top'] is bool
? json['always_on_top'] ?? true
: true,
copySize = max(
1,
min(512,
json['copy_size'] is int ? json['copy_size'] ?? 512 : 512)),
showSearchBar = json['show_search_bar'] is bool
? json['show_search_bar'] ?? true
: true,
globalSearch = json['global_search'] is bool
? json['global_search'] ?? false
: false,
stickerPacks = List<StickerPackConfig>.generate(
((json['sticker_packs'] ?? []) as List<dynamic>).length,
(index) => StickerPackConfig.fromJson(
((json['sticker_packs'] ?? []) as List<dynamic>)[index], wd));

Map<String, dynamic> toJson() => {
'token': token,
'always_on_top': alwaysOnTop,
'copy_size': copySize,
'show_search_bar': showSearchBar,
'sticker_packs': List.generate(stickerPacks.length, (index) => stickerPacks[index].toJson()),
};
'token': token,
'always_on_top': alwaysOnTop,
'copy_size': copySize,
'show_search_bar': showSearchBar,
'global_search': globalSearch,
'sticker_packs': List.generate(
stickerPacks.length, (index) => stickerPacks[index].toJson()),
};
}

class StickerPackConfig {
@@ -36,16 +57,18 @@ class StickerPackConfig {
String coverPath;

StickerPackConfig.fromJson(Map<String, dynamic> json, Directory wd)
: coverFile = File(json['cover_path']).isAbsolute ? File(json['cover_path']) : File(wd.path + json['cover_path']),
coverPath = json['cover_path'],
basePath = json['base_path'],
name = json['name'],
id = json['id'];
: coverFile = File(json['cover_path']).isAbsolute
? File(json['cover_path'])
: File(wd.path + json['cover_path']),
coverPath = json['cover_path'],
basePath = json['base_path'],
name = json['name'],
id = json['id'];

Map<String, dynamic> toJson() => {
'name': name,
'id': id,
'cover_path': coverPath,
'base_path': basePath,
};
}
'name': name,
'id': id,
'cover_path': coverPath,
'base_path': basePath,
};
}
111 changes: 79 additions & 32 deletions lib/pages/home/widgets/right_panel.dart
Original file line number Diff line number Diff line change
@@ -109,12 +109,19 @@ class _RightPanelState extends State<RightPanel> {
child: FittedBox(
alignment: Alignment.topLeft,
fit: BoxFit.fitHeight,
child: Text(
stickers.selectedPack!.name.toUpperCase(),
textAlign: TextAlign.left,
style: TextStyle(
color: theme.headerColor,
fontWeight: FontWeight.w500),
child: ValueListenableBuilder(
valueListenable: settings.globalSearch,
builder: (context, globalSearch, child) {
return Text(
(stickers.filteredWidgets ?? []).isNotEmpty && globalSearch
? (searchController.text.isNotEmpty ? "GLOBAL SEARCH RESULTS" : "ALL STICKERS")
: stickers.selectedPack!.name.toUpperCase(),
textAlign: TextAlign.left,
style: TextStyle(
color: theme.headerColor,
fontWeight: FontWeight.w500),
);
}
),
),
),
@@ -217,36 +224,76 @@ class _RightPanelState extends State<RightPanel> {
textFieldFocus.requestFocus();
}
},
child: TextField(
focusNode: textFieldFocus,
autofocus: true,
controller: searchController,
onChanged: (value) {
query = value;
stickers.filterCurrentPack(value);
if (mounted) {
setState(() => noResult =
(stickers.filteredWidgets ?? [])
.isEmpty);
}
},
maxLines: 1,
cursorColor: theme.inputTextColor,
decoration: InputDecoration(
isDense: true,
border: InputBorder.none,
hintText:
'Search in current pack...',
hintStyle: TextStyle(
color: theme.inputHintColor)),
style: TextStyle(
color: theme.sbTextColor,
fontSize: 16,
),
child: ValueListenableBuilder(
valueListenable: settings.globalSearch,
builder: (context, globalSearch, child) {
return TextField(
focusNode: textFieldFocus,
autofocus: true,
controller: searchController,
onChanged: (value) async {
query = value;
if (globalSearch) {
await stickers.filterAllPacks(value);
} else {
await stickers.filterCurrentPack(value);
}
if (mounted) {
setState(() => noResult =
(stickers.filteredWidgets ?? [])
.isEmpty);
}
},
maxLines: 1,
cursorColor: theme.inputTextColor,
decoration: InputDecoration(
isDense: true,
border: InputBorder.none,
hintText: globalSearch ?
'Search in all packs...' :
'Search in current pack...',
hintStyle: TextStyle(
color: theme.inputHintColor)),
style: TextStyle(
color: theme.sbTextColor,
fontSize: 16,
),
);
}
),
),
),
const SizedBox(width: 4),
MouseRegion(
cursor: SystemMouseCursors.click,
child: ValueListenableBuilder(
valueListenable: settings.globalSearch,
builder: (context, globalSearch, child) {
return GestureDetector(
onTap: () async {
settings.setGlobalSearch(!globalSearch);
if (globalSearch) {
await stickers.filterCurrentPack(searchController.text);
} else {
await stickers.filterAllPacks(searchController.text);
}
if (mounted) {
setState(() => noResult =
(stickers.filteredWidgets ?? [])
.isEmpty);
}
searchFocus.requestFocus();
},
child: Icon(
globalSearch
? FluentSystemIcons.ic_fluent_grid_regular
: FluentSystemIcons.ic_fluent_globe_regular,
size: 18,
color: theme.sbTextColor));
}
),
),
const SizedBox(width: 4),
MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
2 changes: 2 additions & 0 deletions lib/providers/config_provider.dart
Original file line number Diff line number Diff line change
@@ -43,6 +43,7 @@ class ConfigProvider extends ChangeNotifier {
String? token,
int? copySize,
bool? showSearchBar,
bool? globalSearch,
List<StickerPackConfig>? stickerPacks,
}) async {
File configFile = File('${await getPath()}/config.json');
@@ -55,6 +56,7 @@ class ConfigProvider extends ChangeNotifier {
if (token != null) updated.token = token;
if (copySize != null) updated.copySize = copySize;
if (showSearchBar != null) updated.showSearchBar = showSearchBar;
if (globalSearch != null) updated.globalSearch = globalSearch;
if (stickerPacks != null) updated.stickerPacks = stickerPacks;
} else {
updated = await updater(config);
19 changes: 16 additions & 3 deletions lib/providers/settings_provider.dart
Original file line number Diff line number Diff line change
@@ -16,15 +16,19 @@ class SettingsProvider extends ChangeNotifier {

ValueNotifier<bool> alwaysOnTop = ValueNotifier(false);
ValueNotifier<bool> showSearchBar = ValueNotifier(true);
ValueNotifier<bool> globalSearch = ValueNotifier(false);
ValueNotifier<int> copySize = ValueNotifier(512);
SettingsProvider(this.configProvider) {
init();
}

Future<void> init() async {
alwaysOnTop.value = (await configProvider.getConfig()).alwaysOnTop;
showSearchBar.value = (await configProvider.getConfig()).showSearchBar;
copySize.value = (await configProvider.getConfig()).copySize;
final config = await configProvider.getConfig();

alwaysOnTop.value = config.alwaysOnTop;
showSearchBar.value = config.showSearchBar;
globalSearch.value = config.globalSearch;
copySize.value = config.copySize;
}

Future<void> aotSwitch(bool aot) async {
@@ -57,6 +61,15 @@ class SettingsProvider extends ChangeNotifier {
});
}

Future<void> setGlobalSearch(bool global) async {
globalSearch.value = global;

await configProvider.updateConfig(updater: (value) async {
value.globalSearch = global;
return value;
});
}

void setTabWidget(Widget widget, String name) {
tabWidget = widget;
currentTab = name;
47 changes: 38 additions & 9 deletions lib/providers/sticker_provider.dart
Original file line number Diff line number Diff line change
@@ -79,24 +79,30 @@ class StickerProvider extends ChangeNotifier {
if (stickerPacks.isNotEmpty) changePack(index: stickerPacks.length - 1);
}

Future<void> loadCurrentPack() async {
if (selectedPack == null) return;
Future<List<MapEntry<String, SmallSticker>>> loadPackWidgets({
String? id,
int? index,
StickerPackConfig? pack
}) async {
if (id != null) pack = stickerPacks.firstWhere((element) => element.id == id);
if (index != null) pack = stickerPacks[index];

var path = await configProvider.getPath();
var imgPath = Directory(selectedPack!.basePath).isAbsolute ? Directory(selectedPack!.basePath) : Directory('$path${selectedPack!.basePath}');
var imgPath = Directory(pack!.basePath).isAbsolute ? Directory(pack.basePath) : Directory('$path${pack.basePath}');

List<MapEntry<String, SmallSticker>> entryList = [];
if (!await imgPath.exists()) {
selectedPackWidgets = [];
return;
return entryList;
}

var fileList = imgPath.listSync();
fileList.removeWhere((element) => element.path.contains('cover.png'));

var supportedTypes = ['.jpg', '.jpeg', '.jfif', '.png', '.webp', '.gif', '.bmp'];
final supportedTypes = ['.jpg', '.jpeg', '.jfif', '.png', '.webp', '.gif', '.bmp'];

var entryList = <MapEntry<String, SmallSticker>>[];
for (var element in fileList) {
if ((await element.stat()).type != FileSystemEntityType.file) continue;
if (!supportedTypes.contains(extension(element.path).toLowerCase())) continue; //{
if (!supportedTypes.contains(extension(element.path).toLowerCase())) continue;

String keywords = basename(element.path).split('-').last.replaceAll('_', ' ');
String emoji = '';
@@ -108,7 +114,13 @@ class StickerProvider extends ChangeNotifier {
entryList.add(MapEntry(emoji + keywords, SmallSticker(imageFile: File(element.path), emoji: emoji)));
}

selectedPackWidgets = entryList;
return entryList;
}

Future<void> loadCurrentPack() async {
if (selectedPack == null) return;

selectedPackWidgets = await loadPackWidgets(pack: selectedPack);
notifyListeners();
}

@@ -121,6 +133,23 @@ class StickerProvider extends ChangeNotifier {
notifyListeners();
}

Future<void> filterAllPacks(String query) async {
if (query.isEmpty) filteredWidgets = selectedPackWidgets;
List<MapEntry<String, SmallSticker>> results = [];
for (var pack in stickerPacks) {
var packEntries = await loadPackWidgets(pack: pack);
results.addAll(
packEntries.where((element) =>
element.key
.toLowerCase()
.contains(query.toLowerCase())
)
);
}
filteredWidgets = results;
notifyListeners();
}

void setBigSticker(File? imageFile, String? emoji) {
bigStickerEmoji = emoji;
bigSticker = imageFile;

0 comments on commit 1b0ed39

Please sign in to comment.