Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Search Feature #26

Merged
merged 13 commits into from
Sep 25, 2024
3 changes: 3 additions & 0 deletions io.github.halfmexican.Mingle.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
"runtime" : "org.gnome.Platform",
"runtime-version" : "46",
"sdk" : "org.gnome.Sdk",
"sdk-extensions" : [
"org.freedesktop.Sdk.Extension.vala"
],
"command" : "mingle",
"finish-args" : [
"--share=network",
Expand Down
4 changes: 2 additions & 2 deletions src/application.vala
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ namespace Mingle {
};
this.add_action_entries (action_entries, this);
this.set_accels_for_action ("app.quit", { "<primary>q" });
this.set_accels_for_action ("app.select_random", { "<Ctrl>R", "R" });
this.set_accels_for_action ("app.load_batch", {"L"});
this.set_accels_for_action ("app.select_random", { "<Ctrl>R"});
this.set_accels_for_action ("app.load_batch", {"<Ctrl>L"});
}

public override void activate () {
Expand Down
10 changes: 5 additions & 5 deletions src/combined_emoji.vala
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/

using Adw, Gtk, Soup;
using Adw, Gtk, Gdk, Soup;
namespace Mingle {
public class CombinedEmoji : Gtk.Button {
private Gdk.Texture _texture;
private Gdk.Texture _scaled_texture;
private Texture _texture;
private Texture _scaled_texture;
private GLib.Settings settings = new GLib.Settings ("io.github.halfmexican.Mingle");
private EmojiCombination combined_emoji;
public Gtk.Revealer revealer;
public Revealer revealer;
public signal void copied ();

public async CombinedEmoji (EmojiCombination combination_struct, Gtk.RevealerTransitionType transition, out bool image_loaded) {
Expand Down Expand Up @@ -114,4 +114,4 @@ namespace Mingle {
}
}
}
}
}
30 changes: 19 additions & 11 deletions src/emoji_data_manager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ using Json, Soup, Gee;

namespace Mingle {
public class EmojiDataManager {
private Json.Object root_object;
private Json.Object data_object;
private Json.Array supported_emojis;
public HashSet<string> added_combinations;
private Gee.HashMap<string, EmojiData?> emoji_data_map;

public EmojiDataManager () {
public async EmojiDataManager () {
supported_emojis = populate_supported_emojis_array ();
emoji_data_map = new Gee.HashMap<string, EmojiData?> ();
added_combinations = new HashSet<string> ();
Expand All @@ -49,7 +49,8 @@ namespace Mingle {
input_stream.close (null);
data_stream.close (null);

root_object = parser.get_root ().get_object ();
Json.Object root_object = parser.get_root ().get_object ();
data_object = root_object.get_object_member ("data");

// Navigate to known_supported_emoji
Json.Array known_supported_array = root_object.get_array_member ("knownSupportedEmoji");
Expand Down Expand Up @@ -102,8 +103,6 @@ namespace Mingle {
}

public Json.Array get_combinations_array_for_emoji (string emoji_code) {
Json.Object data_object = root_object.get_object_member ("data");

// Get the specific emoji data by code
Json.Object emoji_object = data_object.get_object_member (emoji_code);
if (emoji_object == null) {
Expand Down Expand Up @@ -172,9 +171,9 @@ namespace Mingle {
left_emoji_codepoint = combination_object.get_string_member ("leftEmojiCodepoint"),
right_emoji = combination_object.get_string_member ("rightEmoji"),
right_emoji_codepoint = combination_object.get_string_member ("rightEmojiCodepoint"),
date = combination_object.get_string_member ("date"),
//date = combination_object.get_string_member ("date"),
is_latest = combination_object.get_boolean_member ("isLatest"),
gboard_order = (int) combination_object.get_int_member ("gBoardOrder")
// gboard_order = (int) combination_object.get_int_member ("gBoardOrder")
};
combinations_list.add (combination);
}
Expand All @@ -190,7 +189,6 @@ namespace Mingle {

EmojiData? emoji_data = emoji_data_map[emoji_codepoint];
if (emoji_data != null && emoji_data.combinations == null) {
Json.Object data_object = root_object.get_object_member ("data");
Json.Object? emoji_object = data_object.get_object_member (emoji_codepoint);
if (emoji_object != null) {
emoji_data.combinations = populate_combinations (emoji_object.get_object_member ("combinations"));
Expand All @@ -201,7 +199,6 @@ namespace Mingle {
}

private EmojiData ? create_emoji_data (string emoji_codepoint) {
Json.Object data_object = root_object.get_object_member ("data");
Json.Object? emoji_object = data_object.get_object_member (emoji_codepoint);

if (emoji_object == null) {
Expand All @@ -210,7 +207,18 @@ namespace Mingle {

EmojiData emoji_data = EmojiData ();
emoji_data.alt = emoji_object.get_string_member ("alt");
emoji_data.keywords = emoji_object.get_array_member ("keywords");

// Convert Json.Array to string[]
Json.Array? keywords_array = emoji_object.get_array_member ("keywords");
if (keywords_array != null) {
emoji_data.keywords = new string[keywords_array.get_length ()];
for (int i = 0; i < keywords_array.get_length (); i++) {
emoji_data.keywords[i] = keywords_array.get_string_element (i);
}
} else {
emoji_data.keywords = new string[0];
}

emoji_data.emoji_codepoint = emoji_codepoint;
emoji_data.gboard_order = (int) emoji_object.get_int_member ("gBoardOrder");
emoji_data.combinations = null; // Initialize combinations to null
Expand All @@ -230,4 +238,4 @@ namespace Mingle {
return null;
}
}
}
}
2 changes: 1 addition & 1 deletion src/emoji_label.vala
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace Mingle {
private string emoji;
public string codepoint { get; private set; }
public string alt_name { get; private set; }
public Json.Array? keywords { get; private set; }
public string[] ? keywords { get; private set; }
public Gee.HashMap<string, Gee.List<EmojiCombination?>> combinations { get; private set; }
public EmojiLabel (EmojiData emoji_data) {
this.emoji = codepoint_str_to_emoji (emoji_data.emoji_codepoint);
Expand Down
2 changes: 1 addition & 1 deletion src/emoji_structs.vala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace Mingle {

public struct EmojiData {
public string alt;
public Json.Array keywords;
public string[] keywords;
public string emoji_codepoint;
public int gboard_order;
public Gee.HashMap<string, Gee.List<EmojiCombination?>>? combinations;
Expand Down
26 changes: 23 additions & 3 deletions src/gtk/window.blp
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,33 @@ template $MingleWindow : Adw.ApplicationWindow {
tooltip-text: _("Randomize");
clicked => $select_random();
}
[start]
Button {
icon-name: "edit-find-symbolic";
clicked => $search();
visible: bind search_bar.search-mode-enabled inverted;
}
}
content: CenterBox {
content: Box content_box {
orientation: vertical;

SearchBar search_bar {
visible: true;
key-capture-widget: content_box;
SearchEntry search_entry {
search-delay: 100;
placeholder-text: _("Search emojis");
width-request: 345;
}
}

CenterBox {
shrink-center-last: true;

[start]
ScrolledWindow left_scrolled_window {
propagate-natural-height: true;
hscrollbar-policy: never;
vadjustment: bind right_scrolled_window.vadjustment bidirectional;
hexpand: true;
has-frame: false;
window-placement: top_right;
Expand All @@ -61,6 +79,7 @@ template $MingleWindow : Adw.ApplicationWindow {
max-children-per-line: 6;
min-children-per-line: 1;
selection-mode: single;
valign: start;
}
}

Expand Down Expand Up @@ -101,7 +120,6 @@ template $MingleWindow : Adw.ApplicationWindow {
ScrolledWindow right_scrolled_window {
propagate-natural-height: true;
hscrollbar-policy: never;
vadjustment: bind left_scrolled_window.vadjustment bidirectional;
hexpand: true;
has-frame: false;

Expand All @@ -118,8 +136,10 @@ template $MingleWindow : Adw.ApplicationWindow {
min-children-per-line: 1;
selection-mode: single;
sensitive: false;
valign: start;
}
}
}
};
}
};
Expand Down
76 changes: 72 additions & 4 deletions src/window.vala
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,16 @@ namespace Mingle {
[GtkChild] private unowned Gtk.PopoverMenu popover_menu;
[GtkChild] private unowned Adw.ToolbarView toolbar;
[GtkChild] private unowned Adw.Breakpoint breakpoint;
[GtkChild] private unowned Gtk.SearchBar search_bar;
[GtkChild] private unowned Gtk.SearchEntry search_entry;
[GtkChild] private unowned Gtk.ScrolledWindow left_scrolled_window;
[GtkChild] private unowned Gtk.ScrolledWindow right_scrolled_window;
private GLib.Binding? scroll_binding;

// Class variables
private GLib.Settings settings = new GLib.Settings ("io.github.halfmexican.Mingle");
private Mingle.StyleSwitcher style_switcher = new Mingle.StyleSwitcher ();
private EmojiDataManager emoji_manager = new EmojiDataManager ();
private EmojiDataManager emoji_manager;
private EmojiLabel left_emoji;
private EmojiLabel right_emoji;
// Codepoints
Expand All @@ -60,17 +66,63 @@ namespace Mingle {

public Window (Mingle.Application app) {
// Init
GLib.Object (application: app);
popover_menu.add_child (style_switcher, "style-switcher");
int64 start_time = GLib.get_monotonic_time (); // For measuring load time

GLib.Object (application : app); // constructor
popover_menu.add_child (style_switcher, "style-switcher"); // Add style switcher to popover menu
setup_emoji_manager_async.begin (); // Setup emoji manager and flowboxes
setup_breakpoints ();
apply_toolbar_style ();
update_transition_type ();
setup_emoji_flow_boxes ();
bind_scroll_adjustments ();


// Signals
this.settings.changed.connect (handle_pref_change);
this.bind_property ("is-loading", left_emojis_flow_box, "sensitive", BindingFlags.INVERT_BOOLEAN);
this.combined_scrolled_window.edge_overshot.connect (on_edge_overshot); // Handles loading more emojis on scroll
search_entry.search_changed.connect (() => {
left_emojis_flow_box.invalidate_filter ();
});
left_emojis_flow_box.set_filter_func (filter_emojis);

search_bar.notify["search-mode-enabled"].connect (() => {
if (!search_bar.search_mode_enabled) {
bind_scroll_adjustments ();
} else {
unbind_scroll_adjustments ();
}
});

// Calculate the total time in milliseconds and print/log the result
int64 end_time = GLib.get_monotonic_time ();
double elapsed_time_ms = (end_time - start_time) / 1000.0;
message (@"Window initialization took $elapsed_time_ms ms.");
}

private async void setup_emoji_manager_async () {
// Asynchronously initialize the emoji_manager to avoid blocking the UI thread
emoji_manager = yield new EmojiDataManager ();
// Once the emoji_manager is ready, proceed to initialize the flow boxes
setup_emoji_flow_boxes ();
}

private void bind_scroll_adjustments () {
Gtk.Adjustment left_adjustment = left_scrolled_window.get_vadjustment ();
Gtk.Adjustment right_adjustment = right_scrolled_window.get_vadjustment ();
scroll_binding = left_adjustment.bind_property (
"value",
right_adjustment,
"value",
BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE
);
}

private void unbind_scroll_adjustments () {
if (scroll_binding != null) {
scroll_binding.unbind ();
scroll_binding = null;
}
}

private void handle_pref_change (string key) {
Expand All @@ -84,6 +136,17 @@ namespace Mingle {
}
}

private bool filter_emojis (Gtk.FlowBoxChild child) {
Mingle.EmojiLabel emoji_label = (Mingle.EmojiLabel) child.get_child ();
string search_text = search_entry.text.up ();
foreach (string keyword in emoji_label.keywords) {
if (keyword.up ().contains (search_text)) {
return true;
}
}
return false;
}

private void setup_emoji_flow_boxes () {
connect_flow_box_signals (left_emojis_flow_box, handle_left_emoji_activation);
connect_flow_box_signals (right_emojis_flow_box, handle_right_emoji_activation);
Expand Down Expand Up @@ -252,6 +315,11 @@ namespace Mingle {
child.activate ();
}

[GtkCallback]
private void search () {
search_bar.search_mode_enabled = true;
}

private void create_and_show_toast (string message, int duration) {
var toast = new Adw.Toast (message) {
timeout = duration
Expand Down