diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b836c59..60774a5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,7 +2,6 @@ - @@ -59,8 +58,7 @@ android:name=".MyInputMethodService" android:label="@string/app_name" android:exported="false" - android:permission="android.permission.BIND_INPUT_METHOD" - android:foregroundServiceType="connectedDevice"> + android:permission="android.permission.BIND_INPUT_METHOD"> diff --git a/app/src/main/assets/keyboard_themes/default_darkness/Key_collapse.png b/app/src/main/assets/keyboard_themes/default_darkness/Key_collapse.png new file mode 100644 index 0000000..5ae46ea Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/Key_collapse.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/background.png b/app/src/main/assets/keyboard_themes/default_darkness/background.png new file mode 100644 index 0000000..9070367 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/background.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_0.png b/app/src/main/assets/keyboard_themes/default_darkness/key_0.png new file mode 100644 index 0000000..646899e Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_0.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_1.png b/app/src/main/assets/keyboard_themes/default_darkness/key_1.png new file mode 100644 index 0000000..180b68d Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_1.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_123.png b/app/src/main/assets/keyboard_themes/default_darkness/key_123.png new file mode 100644 index 0000000..db3a42a Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_123.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_2.png b/app/src/main/assets/keyboard_themes/default_darkness/key_2.png new file mode 100644 index 0000000..f047825 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_2.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_3.png b/app/src/main/assets/keyboard_themes/default_darkness/key_3.png new file mode 100644 index 0000000..c26f423 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_3.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_4.png b/app/src/main/assets/keyboard_themes/default_darkness/key_4.png new file mode 100644 index 0000000..51b19a5 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_4.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_5.png b/app/src/main/assets/keyboard_themes/default_darkness/key_5.png new file mode 100644 index 0000000..ff9108b Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_5.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_6.png b/app/src/main/assets/keyboard_themes/default_darkness/key_6.png new file mode 100644 index 0000000..ff836e6 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_6.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_7.png b/app/src/main/assets/keyboard_themes/default_darkness/key_7.png new file mode 100644 index 0000000..4b035ce Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_7.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_8.png b/app/src/main/assets/keyboard_themes/default_darkness/key_8.png new file mode 100644 index 0000000..2ae9620 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_8.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_9.png b/app/src/main/assets/keyboard_themes/default_darkness/key_9.png new file mode 100644 index 0000000..e06c786 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_9.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_a.png b/app/src/main/assets/keyboard_themes/default_darkness/key_a.png new file mode 100644 index 0000000..dda6982 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_a.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_a_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_a_up.png new file mode 100644 index 0000000..4acbc1f Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_a_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_abc.png b/app/src/main/assets/keyboard_themes/default_darkness/key_abc.png new file mode 100644 index 0000000..8458146 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_abc.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_ai.png b/app/src/main/assets/keyboard_themes/default_darkness/key_ai.png new file mode 100644 index 0000000..004fa1e Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_ai.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_amp.png b/app/src/main/assets/keyboard_themes/default_darkness/key_amp.png new file mode 100644 index 0000000..cb5bb62 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_amp.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_asterisk.png b/app/src/main/assets/keyboard_themes/default_darkness/key_asterisk.png new file mode 100644 index 0000000..67f58dd Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_asterisk.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_at.png b/app/src/main/assets/keyboard_themes/default_darkness/key_at.png new file mode 100644 index 0000000..2fc56d5 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_at.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_b.png b/app/src/main/assets/keyboard_themes/default_darkness/key_b.png new file mode 100644 index 0000000..8699032 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_b.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_b_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_b_up.png new file mode 100644 index 0000000..544450e Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_b_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_background.png b/app/src/main/assets/keyboard_themes/default_darkness/key_background.png new file mode 100644 index 0000000..9070367 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_background.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_backslash.png b/app/src/main/assets/keyboard_themes/default_darkness/key_backslash.png new file mode 100644 index 0000000..314e5ef Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_backslash.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_brace_l.png b/app/src/main/assets/keyboard_themes/default_darkness/key_brace_l.png new file mode 100644 index 0000000..a6b9701 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_brace_l.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_brace_r.png b/app/src/main/assets/keyboard_themes/default_darkness/key_brace_r.png new file mode 100644 index 0000000..9282d83 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_brace_r.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_bracket_l.png b/app/src/main/assets/keyboard_themes/default_darkness/key_bracket_l.png new file mode 100644 index 0000000..416a4ec Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_bracket_l.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_bracket_r.png b/app/src/main/assets/keyboard_themes/default_darkness/key_bracket_r.png new file mode 100644 index 0000000..ea9dcc1 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_bracket_r.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_bullet.png b/app/src/main/assets/keyboard_themes/default_darkness/key_bullet.png new file mode 100644 index 0000000..54f95c2 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_bullet.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_c.png b/app/src/main/assets/keyboard_themes/default_darkness/key_c.png new file mode 100644 index 0000000..74abb95 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_c.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_c_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_c_up.png new file mode 100644 index 0000000..861a680 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_c_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_caret.png b/app/src/main/assets/keyboard_themes/default_darkness/key_caret.png new file mode 100644 index 0000000..75f80c8 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_caret.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_colon.png b/app/src/main/assets/keyboard_themes/default_darkness/key_colon.png new file mode 100644 index 0000000..5983186 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_colon.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_comma.png b/app/src/main/assets/keyboard_themes/default_darkness/key_comma.png new file mode 100644 index 0000000..55a4f4f Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_comma.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_d.png b/app/src/main/assets/keyboard_themes/default_darkness/key_d.png new file mode 100644 index 0000000..eb97a6d Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_d.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_d_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_d_up.png new file mode 100644 index 0000000..83edc30 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_d_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_del.png b/app/src/main/assets/keyboard_themes/default_darkness/key_del.png new file mode 100644 index 0000000..44ab866 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_del.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_dollar.png b/app/src/main/assets/keyboard_themes/default_darkness/key_dollar.png new file mode 100644 index 0000000..90bbb01 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_dollar.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_dot.png b/app/src/main/assets/keyboard_themes/default_darkness/key_dot.png new file mode 100644 index 0000000..bc61898 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_dot.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_e.png b/app/src/main/assets/keyboard_themes/default_darkness/key_e.png new file mode 100644 index 0000000..177a1fb Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_e.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_e_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_e_up.png new file mode 100644 index 0000000..efd527e Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_e_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_emoji.png b/app/src/main/assets/keyboard_themes/default_darkness/key_emoji.png new file mode 100644 index 0000000..e6d1101 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_emoji.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_equal.png b/app/src/main/assets/keyboard_themes/default_darkness/key_equal.png new file mode 100644 index 0000000..61b30cb Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_equal.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_euro.png b/app/src/main/assets/keyboard_themes/default_darkness/key_euro.png new file mode 100644 index 0000000..e11ba5e Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_euro.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_exclam.png b/app/src/main/assets/keyboard_themes/default_darkness/key_exclam.png new file mode 100644 index 0000000..85d492f Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_exclam.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_f.png b/app/src/main/assets/keyboard_themes/default_darkness/key_f.png new file mode 100644 index 0000000..0b6f289 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_f.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_f_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_f_up.png new file mode 100644 index 0000000..1f7c89e Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_f_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_g.png b/app/src/main/assets/keyboard_themes/default_darkness/key_g.png new file mode 100644 index 0000000..ca2d681 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_g.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_g_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_g_up.png new file mode 100644 index 0000000..5b2907f Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_g_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_gt.png b/app/src/main/assets/keyboard_themes/default_darkness/key_gt.png new file mode 100644 index 0000000..01f520e Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_gt.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_h.png b/app/src/main/assets/keyboard_themes/default_darkness/key_h.png new file mode 100644 index 0000000..ce2272f Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_h.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_h_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_h_up.png new file mode 100644 index 0000000..d4a91be Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_h_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_hash.png b/app/src/main/assets/keyboard_themes/default_darkness/key_hash.png new file mode 100644 index 0000000..cfd1b72 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_hash.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_i.png b/app/src/main/assets/keyboard_themes/default_darkness/key_i.png new file mode 100644 index 0000000..2dbe930 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_i.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_i_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_i_up.png new file mode 100644 index 0000000..597a148 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_i_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_j.png b/app/src/main/assets/keyboard_themes/default_darkness/key_j.png new file mode 100644 index 0000000..a15c560 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_j.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_j_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_j_up.png new file mode 100644 index 0000000..f21bea5 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_j_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_k.png b/app/src/main/assets/keyboard_themes/default_darkness/key_k.png new file mode 100644 index 0000000..6964cc9 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_k.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_k_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_k_up.png new file mode 100644 index 0000000..c282c4e Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_k_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_l.png b/app/src/main/assets/keyboard_themes/default_darkness/key_l.png new file mode 100644 index 0000000..82ab615 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_l.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_l_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_l_up.png new file mode 100644 index 0000000..d69311f Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_l_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_lt.png b/app/src/main/assets/keyboard_themes/default_darkness/key_lt.png new file mode 100644 index 0000000..d211bca Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_lt.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_m.png b/app/src/main/assets/keyboard_themes/default_darkness/key_m.png new file mode 100644 index 0000000..1314d2a Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_m.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_m_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_m_up.png new file mode 100644 index 0000000..cf1f09c Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_m_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_minus.png b/app/src/main/assets/keyboard_themes/default_darkness/key_minus.png new file mode 100644 index 0000000..6abe168 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_minus.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_money.png b/app/src/main/assets/keyboard_themes/default_darkness/key_money.png new file mode 100644 index 0000000..2db7389 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_money.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_n.png b/app/src/main/assets/keyboard_themes/default_darkness/key_n.png new file mode 100644 index 0000000..417582f Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_n.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_n_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_n_up.png new file mode 100644 index 0000000..49359c6 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_n_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_o.png b/app/src/main/assets/keyboard_themes/default_darkness/key_o.png new file mode 100644 index 0000000..c3d2331 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_o.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_o_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_o_up.png new file mode 100644 index 0000000..47d8d1a Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_o_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_p.png b/app/src/main/assets/keyboard_themes/default_darkness/key_p.png new file mode 100644 index 0000000..63f7676 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_p.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_p_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_p_up.png new file mode 100644 index 0000000..f5a8171 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_p_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_paren_l.png b/app/src/main/assets/keyboard_themes/default_darkness/key_paren_l.png new file mode 100644 index 0000000..f3ce1be Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_paren_l.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_paren_r.png b/app/src/main/assets/keyboard_themes/default_darkness/key_paren_r.png new file mode 100644 index 0000000..a4c3f5d Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_paren_r.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_percent.png b/app/src/main/assets/keyboard_themes/default_darkness/key_percent.png new file mode 100644 index 0000000..a8fc219 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_percent.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_pipe.png b/app/src/main/assets/keyboard_themes/default_darkness/key_pipe.png new file mode 100644 index 0000000..c563748 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_pipe.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_plus.png b/app/src/main/assets/keyboard_themes/default_darkness/key_plus.png new file mode 100644 index 0000000..d918be8 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_plus.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_pound.png b/app/src/main/assets/keyboard_themes/default_darkness/key_pound.png new file mode 100644 index 0000000..f5ff444 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_pound.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_q.png b/app/src/main/assets/keyboard_themes/default_darkness/key_q.png new file mode 100644 index 0000000..20c6013 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_q.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_q_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_q_up.png new file mode 100644 index 0000000..2c07b9c Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_q_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_question.png b/app/src/main/assets/keyboard_themes/default_darkness/key_question.png new file mode 100644 index 0000000..070e5e2 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_question.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_quote.png b/app/src/main/assets/keyboard_themes/default_darkness/key_quote.png new file mode 100644 index 0000000..d127a2d Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_quote.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_quote_d.png b/app/src/main/assets/keyboard_themes/default_darkness/key_quote_d.png new file mode 100644 index 0000000..2300064 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_quote_d.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_r.png b/app/src/main/assets/keyboard_themes/default_darkness/key_r.png new file mode 100644 index 0000000..308121f Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_r.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_r_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_r_up.png new file mode 100644 index 0000000..0ce70c5 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_r_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_revoke.png b/app/src/main/assets/keyboard_themes/default_darkness/key_revoke.png new file mode 100644 index 0000000..ec909d2 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_revoke.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_s.png b/app/src/main/assets/keyboard_themes/default_darkness/key_s.png new file mode 100644 index 0000000..b582163 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_s.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_s_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_s_up.png new file mode 100644 index 0000000..495bb9b Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_s_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_semicolon.png b/app/src/main/assets/keyboard_themes/default_darkness/key_semicolon.png new file mode 100644 index 0000000..2be938c Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_semicolon.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_send.png b/app/src/main/assets/keyboard_themes/default_darkness/key_send.png new file mode 100644 index 0000000..b1187f3 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_send.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_slash.png b/app/src/main/assets/keyboard_themes/default_darkness/key_slash.png new file mode 100644 index 0000000..13c3dbe Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_slash.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_space.png b/app/src/main/assets/keyboard_themes/default_darkness/key_space.png new file mode 100644 index 0000000..6081738 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_space.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_symbols_123.png b/app/src/main/assets/keyboard_themes/default_darkness/key_symbols_123.png new file mode 100644 index 0000000..94ea077 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_symbols_123.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_symbols_more.png b/app/src/main/assets/keyboard_themes/default_darkness/key_symbols_more.png new file mode 100644 index 0000000..559882a Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_symbols_more.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_t.png b/app/src/main/assets/keyboard_themes/default_darkness/key_t.png new file mode 100644 index 0000000..759e7fc Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_t.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_t_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_t_up.png new file mode 100644 index 0000000..4be51a6 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_t_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_tilde.png b/app/src/main/assets/keyboard_themes/default_darkness/key_tilde.png new file mode 100644 index 0000000..ff434e2 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_tilde.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_u.png b/app/src/main/assets/keyboard_themes/default_darkness/key_u.png new file mode 100644 index 0000000..a5ec74e Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_u.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_u_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_u_up.png new file mode 100644 index 0000000..011a19c Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_u_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_underscore.png b/app/src/main/assets/keyboard_themes/default_darkness/key_underscore.png new file mode 100644 index 0000000..3fe234b Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_underscore.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_up.png new file mode 100644 index 0000000..342e76b Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_up_upper.png b/app/src/main/assets/keyboard_themes/default_darkness/key_up_upper.png new file mode 100644 index 0000000..6825053 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_up_upper.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_v.png b/app/src/main/assets/keyboard_themes/default_darkness/key_v.png new file mode 100644 index 0000000..9250d6e Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_v.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_v_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_v_up.png new file mode 100644 index 0000000..c66069b Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_v_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_w.png b/app/src/main/assets/keyboard_themes/default_darkness/key_w.png new file mode 100644 index 0000000..44b6bd3 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_w.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_w_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_w_up.png new file mode 100644 index 0000000..987c3e2 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_w_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_x.png b/app/src/main/assets/keyboard_themes/default_darkness/key_x.png new file mode 100644 index 0000000..0e9ceaf Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_x.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_x_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_x_up.png new file mode 100644 index 0000000..b5e5424 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_x_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_y.png b/app/src/main/assets/keyboard_themes/default_darkness/key_y.png new file mode 100644 index 0000000..a41f9d1 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_y.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_y_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_y_up.png new file mode 100644 index 0000000..5ed6bd9 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_y_up.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_z.png b/app/src/main/assets/keyboard_themes/default_darkness/key_z.png new file mode 100644 index 0000000..6304705 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_z.png differ diff --git a/app/src/main/assets/keyboard_themes/default_darkness/key_z_up.png b/app/src/main/assets/keyboard_themes/default_darkness/key_z_up.png new file mode 100644 index 0000000..b1e3066 Binary files /dev/null and b/app/src/main/assets/keyboard_themes/default_darkness/key_z_up.png differ diff --git a/app/src/main/java/com/example/myapplication/MyInputMethodService.kt b/app/src/main/java/com/example/myapplication/MyInputMethodService.kt index 0d7484e..4162190 100644 --- a/app/src/main/java/com/example/myapplication/MyInputMethodService.kt +++ b/app/src/main/java/com/example/myapplication/MyInputMethodService.kt @@ -1,13 +1,10 @@ package com.example.myapplication -import android.app.NotificationChannel -import android.app.NotificationManager import android.content.Context import android.content.res.ColorStateList import android.graphics.Color import android.inputmethodservice.InputMethodService import android.media.AudioManager -import android.os.Build import android.os.Handler import android.os.Looper import android.util.Log @@ -22,7 +19,6 @@ import android.widget.PopupWindow import android.widget.TextView import androidx.annotation.ColorInt import androidx.annotation.DrawableRes -import androidx.core.app.NotificationCompat import com.example.myapplication.data.WordDictionary import com.example.myapplication.data.LanguageModelLoader import com.example.myapplication.theme.ThemeManager @@ -86,8 +82,6 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment { companion object { private const val TAG = "MyIME" - private const val NOTIFICATION_CHANNEL_ID = "input_method_channel" - private const val NOTIFICATION_ID = 1 private const val ZWJ = 0x200D // ZERO WIDTH JOINER private const val VS16 = 0xFE0F // VARIATION SELECTOR-16 (emoji) @@ -266,41 +260,9 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment { } }.start() - createNotificationChannelIfNeeded() - tryStartForegroundSafe() } // 输入法状态变化 - private fun createNotificationChannelIfNeeded() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val channel = NotificationChannel( - NOTIFICATION_CHANNEL_ID, - "输入法服务", - NotificationManager.IMPORTANCE_LOW - ).apply { description = "保持输入法服务运行" } - - val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - manager.createNotificationChannel(channel) - } - } - - private fun tryStartForegroundSafe() { - try { - val notification = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID) - .setContentTitle("输入法服务") - .setContentText("输入法正在运行") - .setSmallIcon(android.R.drawable.ic_dialog_info) - .setPriority(NotificationCompat.PRIORITY_LOW) - .setOngoing(true) - .build() - - startForeground(NOTIFICATION_ID, notification) - Log.i(TAG, "startForeground success") - } catch (e: Exception) { - Log.w(TAG, "startForeground failed: ${e.message}") - } - } - // 创建输入视图:此处只负责选择主键盘 override fun onCreateInputView(): View { val keyboard = ensureMainKeyboard() @@ -356,6 +318,7 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment { super.onFinishInputView(finishingInput) isInputViewShownFlag = false stopRepeatDelete() + aiKeyboard?.cancelAiStream() // 清理本次输入状态 clearEditorState() @@ -374,6 +337,7 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment { override fun onDestroy() { ThemeManager.removeThemeChangeListener(themeListener) stopRepeatDelete() + aiKeyboard?.cancelAiStream() super.onDestroy() } @@ -649,6 +613,7 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment { override fun onConfigurationChanged(newConfig: Configuration) { // 先清理缓存,避免复用旧 View currentKeyboardView = null + aiKeyboard?.cancelAiStream() mainKeyboardView = null numberKeyboardView = null diff --git a/app/src/main/java/com/example/myapplication/keyboard/AiKeyboard.kt b/app/src/main/java/com/example/myapplication/keyboard/AiKeyboard.kt index 6d0a9b1..f9e34e0 100644 --- a/app/src/main/java/com/example/myapplication/keyboard/AiKeyboard.kt +++ b/app/src/main/java/com/example/myapplication/keyboard/AiKeyboard.kt @@ -9,9 +9,11 @@ import android.graphics.Paint import android.graphics.Typeface import android.os.Handler import android.os.Looper +import android.os.SystemClock import android.view.Gravity import android.view.View import android.view.ViewGroup +import android.view.ViewConfiguration import android.widget.ImageView import android.widget.LinearLayout import android.widget.ScrollView @@ -36,6 +38,7 @@ import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import okhttp3.Call +import kotlin.math.abs import kotlin.math.min import com.example.myapplication.network.BehaviorReporter @@ -47,16 +50,16 @@ class AiKeyboard( private val mainHandler = Handler(Looper.getMainLooper()) private val uiScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) - // ✅ 卡片选中的 characterId(SSE 参数) + // ✅ 卡片选中的 characterId(SSE 参数) private var selectedCharacterId: Int? = null - // ✅ Paste 得到的内容(SSE message) + // ✅ Paste 得到的内容(SSE message) private var lastPastedText: String? = null // ✅ 记录“上次从卡片填入到输入框”的文本,用于覆盖 private var lastFilledText: String? = null - // 输出容器 + // 杈撳嚭瀹瑰櫒 private val messagesContainer: LinearLayout by lazy { val res = env.ctx.resources val id = res.getIdentifier("container_messages", "id", env.ctx.packageName) @@ -72,7 +75,23 @@ class AiKeyboard( } private var currentAssistantTextView: TextView? = null - private val streamBuffer = StringBuilder() + private val incomingBuffer = StringBuilder() + private val incomingLock = Any() + private val pendingBuffer = StringBuilder() + private val displayBuffer = StringBuilder() + @Volatile private var isTickerRunning = false + @Volatile private var streamDone = false + private var lastScrollAtMs = 0L + private val splitTag = "" + private val scrollThrottleMs = 100L + private val autoScrollThresholdPx by lazy { + (env.ctx.resources.displayMetrics.density * 64f).toInt() + } + private val typewriterRunnable = object : Runnable { + override fun run() { + tickTypewriter() + } + } /** * ✅ inflate 一条消息(item_ai_message.xml) @@ -115,7 +134,7 @@ class AiKeyboard( } messagesContainer.addView(itemView) - scrollToBottom() + maybeScrollToBottom(force = true) return textView } @@ -125,54 +144,223 @@ class AiKeyboard( } } - private fun onLlmChunk(data: String) { - if (data == ":\n\n") return + private fun maybeScrollToBottom(force: Boolean = false) { + val now = SystemClock.uptimeMillis() + if (now - lastScrollAtMs < scrollThrottleMs) return + if (!force && !isNearBottom()) return + lastScrollAtMs = now + scrollToBottom() + } + private fun isNearBottom(): Boolean { + val child = messagesScrollView.getChildAt(0) ?: return true + val diff = child.bottom - (messagesScrollView.height + messagesScrollView.scrollY) + return diff <= autoScrollThresholdPx + } + + private sealed class TypewriterToken { + data class Text(val value: String) : TypewriterToken() + object Split : TypewriterToken() + } + + private fun enqueueChunk(data: String) { + if (data.isEmpty() || data == ":\n\n") return + synchronized(incomingLock) { + incomingBuffer.append(data) + } + startTypewriterIfNeeded() + } + + private fun startTypewriterIfNeeded() { mainHandler.post { - if (currentAssistantTextView == null) { - currentAssistantTextView = addAssistantMessage("") - streamBuffer.clear() - } - - streamBuffer.append(data) - var text = streamBuffer.toString().replace(":\n\n", "") - - val splitTag = "" - var index = text.indexOf(splitTag) - - while (index != -1) { - val before = text.substring(0, index) - currentAssistantTextView?.text = before - scrollToBottom() - - currentAssistantTextView = addAssistantMessage("") - text = text.substring(index + splitTag.length) - index = text.indexOf(splitTag) - } - - currentAssistantTextView?.text = text - scrollToBottom() - - streamBuffer.clear() - streamBuffer.append(text) + if (isTickerRunning) return@post + isTickerRunning = true + mainHandler.post(typewriterRunnable) } } - private fun onLlmDone() { - cancelAiStream() - mainHandler.post { - streamBuffer.clear() + private fun stopTypewriter(clearBuffers: Boolean, clearUi: Boolean) { + isTickerRunning = false + mainHandler.removeCallbacks(typewriterRunnable) + if (clearBuffers) { + synchronized(incomingLock) { + incomingBuffer.setLength(0) + } + pendingBuffer.setLength(0) + displayBuffer.setLength(0) + streamDone = false + lastScrollAtMs = 0L + } + if (clearUi) { currentAssistantTextView = null } } + private fun tickTypewriter() { + if (!isTickerRunning) return + + drainIncomingToPending() + val incomingLen = incomingLength() + + if (pendingBuffer.isEmpty() && incomingLen == 0) { + if (streamDone) { + displayBuffer.clear() + currentAssistantTextView = null + streamDone = false + } + isTickerRunning = false + return + } + + val totalBacklog = pendingBuffer.length + incomingLen + val units = computeUnitsPerTick(totalBacklog) + var consumedAny = false + + repeat(units) { + val token = consumeNextToken() ?: return@repeat + consumedAny = true + when (token) { + is TypewriterToken.Text -> { + ensureCurrentAssistant() + appendToCurrent(token.value) + } + TypewriterToken.Split -> { + handleSplitTag() + } + } + } + + if (consumedAny) { + maybeScrollToBottom() + } + + val delayMs = computeTickDelayMs(totalBacklog) + mainHandler.postDelayed(typewriterRunnable, delayMs) + } + + private fun drainIncomingToPending() { + synchronized(incomingLock) { + if (incomingBuffer.isNotEmpty()) { + pendingBuffer.append(incomingBuffer) + incomingBuffer.setLength(0) + } + } + } + + private fun incomingLength(): Int { + return synchronized(incomingLock) { + incomingBuffer.length + } + } + + private fun consumeNextToken(): TypewriterToken? { + if (pendingBuffer.isEmpty()) return null + + val matchLen = matchSplitPrefixLength() + if (matchLen == splitTag.length) { + pendingBuffer.delete(0, splitTag.length) + return TypewriterToken.Split + } + if (matchLen == pendingBuffer.length && matchLen < splitTag.length) { + if (!streamDone) { + return null + } + } + + val first = pendingBuffer[0] + val token = if (first.isHighSurrogate() && + pendingBuffer.length > 1 && + pendingBuffer[1].isLowSurrogate() + ) { + pendingBuffer.substring(0, 2).also { pendingBuffer.delete(0, 2) } + } else { + pendingBuffer.substring(0, 1).also { pendingBuffer.delete(0, 1) } + } + + return TypewriterToken.Text(token) + } + + private fun matchSplitPrefixLength(): Int { + val max = min(pendingBuffer.length, splitTag.length) + var i = 0 + while (i < max && pendingBuffer[i] == splitTag[i]) { + i++ + } + return i + } + + private fun ensureCurrentAssistant() { + if (currentAssistantTextView == null) { + currentAssistantTextView = addAssistantMessage("") + displayBuffer.clear() + } + } + + private fun appendToCurrent(text: String) { + displayBuffer.append(text) + currentAssistantTextView?.text = displayBuffer.toString() + } + + private fun handleSplitTag() { + if (currentAssistantTextView == null) { + currentAssistantTextView = addAssistantMessage("") + } + currentAssistantTextView?.text = displayBuffer.toString() + currentAssistantTextView = addAssistantMessage("") + displayBuffer.clear() + } + + private fun computeUnitsPerTick(backlog: Int): Int { + return when { + backlog > 2000 -> 8 + backlog > 1200 -> 5 + backlog > 600 -> 3 + backlog > 300 -> 2 + else -> 1 + } + } + + private fun computeTickDelayMs(backlog: Int): Long { + return when { + backlog > 2000 -> 12L + backlog > 1200 -> 14L + backlog > 600 -> 18L + backlog > 300 -> 22L + else -> 30L + } + } + + private fun onLlmChunk(data: String) { + enqueueChunk(data) + } + + private fun onLlmDone() { + stopStreamCall() + mainHandler.post { + streamDone = true + if (!isTickerRunning) { + drainIncomingToPending() + if (pendingBuffer.isEmpty()) { + displayBuffer.clear() + currentAssistantTextView = null + streamDone = false + } else { + isTickerRunning = true + mainHandler.post(typewriterRunnable) + } + } + } + } + // ✅ 关键:调用 POST /chat/talk 的 SSE,并渲染到输出区 private fun startTalkStream(characterId: Int, message: String) { // 每次发起新对话:清空输出区(你如果想保留历史,把这行删掉) + stopTypewriter(clearBuffers = true, clearUi = true) + streamDone = false messagesContainer.removeAllViews() // 取消旧流 - currentStreamCall?.cancel() + stopStreamCall() currentStreamCall = NetworkClient.startChatTalkStream( characterId = characterId, @@ -231,11 +419,22 @@ class AiKeyboard( ) } - fun cancelAiStream() { + private fun stopStreamCall() { currentStreamCall?.cancel() currentStreamCall = null } + fun cancelAiStream() { + stopStreamCall() + if (Looper.myLooper() == Looper.getMainLooper()) { + stopTypewriter(clearBuffers = true, clearUi = true) + } else { + mainHandler.post { + stopTypewriter(clearBuffers = true, clearUi = true) + } + } + } + override val rootView: View = run { val res = env.ctx.resources val layoutId = res.getIdentifier("ai_keyboard", "layout", env.ctx.packageName) @@ -313,33 +512,74 @@ class AiKeyboard( // Paste:读取剪贴板第一条 -> 保存 lastPastedText,并显示到 completion_text val pasteBtnId = res.getIdentifier("keyboard_button_Paste", "id", pkg) val completionTextId = res.getIdentifier("completion_text", "id", pkg) + val pasteContainerId = res.getIdentifier("paste_container", "id", pkg) + val pasteAction: () -> Unit = { + val text = readClipboardFirstText() + lastPastedText = text + + if (completionTextId != 0) { + rootView.findViewById(completionTextId)?.text = + if (text.isNullOrBlank()) "" else text + } + } + val touchSlop = ViewConfiguration.get(env.ctx).scaledTouchSlop + fun attachTapToPaste(target: View?) { + if (target == null) return + var downX = 0f + var downY = 0f + var moved = false + target.setOnTouchListener { _, event -> + when (event.actionMasked) { + android.view.MotionEvent.ACTION_DOWN -> { + downX = event.x + downY = event.y + moved = false + false + } + android.view.MotionEvent.ACTION_MOVE -> { + if (abs(event.x - downX) > touchSlop || abs(event.y - downY) > touchSlop) { + moved = true + } + false + } + android.view.MotionEvent.ACTION_UP -> { + if (!moved) { + pasteAction() + true + } else { + false + } + } + else -> false + } + } + } + if (pasteContainerId != 0) { + rootView.findViewById(pasteContainerId)?.setOnClickListener { + pasteAction() + } + } if (pasteBtnId != 0) { rootView.findViewById(pasteBtnId)?.setOnClickListener { - val text = readClipboardFirstText() - lastPastedText = text - - if (completionTextId != 0) { - rootView.findViewById(completionTextId)?.text = - if (text.isNullOrBlank()) "" else text - } + pasteAction() } } // HorizontalScrollView:点击事件与Paste按钮相同 - val scrollViewId = res.getIdentifier("completion_container", "id", pkg) - if (scrollViewId != 0) { - rootView.findViewById(scrollViewId)?.setOnClickListener { - val text = readClipboardFirstText() - lastPastedText = text - - if (completionTextId != 0) { - rootView.findViewById(completionTextId)?.text = - if (text.isNullOrBlank()) "" else text + val pasteScrollId = res.getIdentifier("completion_scroll", "id", pkg) + val completionContainerId = res.getIdentifier("completion_container", "id", pkg) + val pasteTargets = listOf(pasteScrollId, completionContainerId).distinct() + for (targetId in pasteTargets) { + if (targetId != 0) { + val targetView = rootView.findViewById(targetId) + targetView?.setOnClickListener { + pasteAction() } + attachTapToPaste(targetView) } } - // ✅ Delete:沿用 MyInputMethodService.deleteOne() + // ✅ Delete:沿用 MyInputMethodService.deleteOne() val deleteBtnId = res.getIdentifier("keyboard_button_Delete", "id", pkg) if (deleteBtnId != 0) { rootView.findViewById(deleteBtnId)?.setOnClickListener { @@ -430,7 +670,7 @@ class AiKeyboard( "id" to item.characterId, "name" to item.characterName, ) - // ✅ SSE 要的是 characterId,不是 id + // SSE 要的是 characterId,不是 id selectedCharacterId = item.characterId val res = env.ctx.resources @@ -486,7 +726,7 @@ class AiKeyboard( return clip.getItemAt(0).coerceToText(env.ctx)?.toString() } - /** + /** * ✅ 将卡片文本填入宿主输入框,并覆盖上一次“卡片填入”的内容 * 覆盖策略(安全版): * - 仅当光标前的文本 == lastFilledText 时,才删除那段并覆盖 @@ -511,7 +751,7 @@ class AiKeyboard( } } - /** ✅ 清空宿主输入框(当前编辑框) */ + /*清空宿主输入框(当前编辑框) */ private fun clearEditorAll() { val ic = env.getInputConnection() ?: return @@ -532,7 +772,7 @@ class AiKeyboard( } } - // ========= 换肤相关(保留你原有逻辑) ========= + // ========= 换肤相关========= private fun applyKeyBackground(root: View, viewIdName: String, drawableName: String? = null) { val res = env.ctx.resources @@ -589,7 +829,7 @@ class AiKeyboard( } } - /** 包一层 try-catch,避免任何地方异常直接白屏 */ + /* 包一层 try-catch,避免任何地方异常直接白屏*/ private inline fun guard(tag: String, block: () -> Unit) { try { block() diff --git a/app/src/main/java/com/example/myapplication/theme/ThemeManager.kt b/app/src/main/java/com/example/myapplication/theme/ThemeManager.kt index f1a0a0a..1b66974 100644 --- a/app/src/main/java/com/example/myapplication/theme/ThemeManager.kt +++ b/app/src/main/java/com/example/myapplication/theme/ThemeManager.kt @@ -1,7 +1,9 @@ package com.example.myapplication.theme +import android.content.ComponentCallbacks import android.content.Context import android.content.res.AssetManager +import android.content.res.Configuration import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.drawable.BitmapDrawable @@ -18,6 +20,12 @@ object ThemeManager { // SharedPreferences 保存当前主题名 private const val PREF_NAME = "ime_theme_prefs" private const val KEY_CURRENT_THEME = "current_theme" + private const val KEY_IS_MANUAL_THEME = "is_manual_theme" + + @Volatile + private var isManualTheme = false + + private var darkModeComponentCallbacks: ComponentCallbacks? = null // 当前主题名(如 "default") @Volatile @@ -113,12 +121,30 @@ object ThemeManager { * - 默认使用 "default" * - 加载该主题的所有图片到缓存 */ + private fun isDarkMode(context: Context): Boolean { + val nightModeFlags = context.resources.configuration.uiMode and + Configuration.UI_MODE_NIGHT_MASK + return nightModeFlags == Configuration.UI_MODE_NIGHT_YES + } + fun init(context: Context) { if (currentThemeName != null) return val prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) - val name = prefs.getString(KEY_CURRENT_THEME, "default") ?: "default" - setCurrentTheme(context, name) + isManualTheme = prefs.getBoolean(KEY_IS_MANUAL_THEME, false) + + if (!isManualTheme) { + updateThemeForSystemMode(context) + context.registerSystemDarkModeListener() + } else { + val name = prefs.getString(KEY_CURRENT_THEME, "default") ?: "default" + setCurrentTheme(context, name, true) + } + } + + private fun updateThemeForSystemMode(context: Context) { + val defaultTheme = if (isDarkMode(context)) "default_darkness" else "default" + setCurrentTheme(context, defaultTheme, false) } /** @@ -127,14 +153,21 @@ object ThemeManager { * - 写 SharedPreferences * - 重新加载该主题的全部图片到缓存 */ - fun setCurrentTheme(context: Context, themeName: String) { + fun setCurrentTheme(context: Context, themeName: String, isManual: Boolean = true) { currentThemeName = themeName + isManualTheme = isManual context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) .edit() .putString(KEY_CURRENT_THEME, themeName) + .putBoolean(KEY_IS_MANUAL_THEME, isManual) .apply() + // 如果是手动选择主题,取消系统模式监听 + if (isManual) { + context.unregisterSystemDarkModeListener() + } + val newFilePathCache: MutableMap = ConcurrentHashMap() drawableCache = ConcurrentHashMap() filePathCache = newFilePathCache @@ -155,6 +188,40 @@ object ThemeManager { fun getCurrentThemeName(): String? = currentThemeName + private fun Context.registerSystemDarkModeListener() { + try { + darkModeComponentCallbacks?.let { + unregisterComponentCallbacks(it) + } + + val callbacks = object : ComponentCallbacks { + override fun onConfigurationChanged(newConfig: Configuration) { + if (!isManualTheme) { + updateThemeForSystemMode(this@registerSystemDarkModeListener) + } + } + + override fun onLowMemory() {} + } + + registerComponentCallbacks(callbacks) + darkModeComponentCallbacks = callbacks + } catch (e: Exception) { + // 忽略注册失败 + } + } + + private fun Context.unregisterSystemDarkModeListener() { + try { + darkModeComponentCallbacks?.let { + unregisterComponentCallbacks(it) + darkModeComponentCallbacks = null + } + } catch (e: Exception) { + // 忽略取消注册失败 + } + } + /** * 扫描某个主题目录下的所有 png/jpg/webp 文件, * 用“文件名(去掉扩展名,小写)”作为 keyName,构造缓存。 diff --git a/app/src/main/java/com/example/myapplication/ui/home/HomeFragment.kt b/app/src/main/java/com/example/myapplication/ui/home/HomeFragment.kt index 3650d53..067bc3b 100644 --- a/app/src/main/java/com/example/myapplication/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/example/myapplication/ui/home/HomeFragment.kt @@ -476,9 +476,8 @@ class HomeFragment : Fragment() { bottomSheetBehavior.isHideable = false bottomSheetBehavior.isFitToContents = false bottomSheetBehavior.halfExpandedRatio = 0.7f - - // ✅ 固定初始高度,避免每次计算导致跳动 - bottomSheetBehavior.peekHeight = dpToPx(260) // 你想要多少就写多少 + + applyAdaptivePeekHeight(root) bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED bottomSheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { @@ -495,6 +494,24 @@ class HomeFragment : Fragment() { return (dp * resources.displayMetrics.density).toInt() } + private fun applyAdaptivePeekHeight(root: View) { + root.post { + val maxByContent = maxPeekHeightBelowAnchor(root, R.id.rechargeButton, dpToPx(12)) + bottomSheetBehavior.peekHeight = maxByContent.coerceAtLeast(0) + } + } + + private fun maxPeekHeightBelowAnchor(root: View, anchorId: Int, marginPx: Int): Int { + val anchor = root.findViewById(anchorId) ?: return Int.MAX_VALUE + val rootLoc = IntArray(2) + val anchorLoc = IntArray(2) + root.getLocationInWindow(rootLoc) + anchor.getLocationInWindow(anchorLoc) + val rootBottom = rootLoc[1] + root.height + val anchorBottom = anchorLoc[1] + anchor.height + return (rootBottom - anchorBottom - marginPx).coerceAtLeast(0) + } + // ---------------- Tabs ---------------- private fun setupTopTabs() { diff --git a/app/src/main/java/com/example/myapplication/ui/keyboard/MyKeyboard.kt b/app/src/main/java/com/example/myapplication/ui/keyboard/MyKeyboard.kt index 31694cb..8abb75b 100644 --- a/app/src/main/java/com/example/myapplication/ui/keyboard/MyKeyboard.kt +++ b/app/src/main/java/com/example/myapplication/ui/keyboard/MyKeyboard.kt @@ -13,6 +13,7 @@ import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.RecyclerView +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.example.myapplication.R import com.example.myapplication.network.ApiResponse import com.example.myapplication.network.AuthEvent @@ -30,6 +31,7 @@ class MyKeyboard : Fragment() { private lateinit var btnSave: TextView private lateinit var adapter: KeyboardAdapter private lateinit var loadingOverlay: LoadingOverlay + private lateinit var swipeRefresh: SwipeRefreshLayout override fun onCreateView( inflater: LayoutInflater, @@ -46,6 +48,8 @@ class MyKeyboard : Fragment() { rv = view.findViewById(R.id.rv_keyboard) btnSave = view.findViewById(R.id.btn_keyboard) + swipeRefresh = view.findViewById(R.id.swipeRefresh) + swipeRefresh.setOnRefreshListener { loadList() } adapter = KeyboardAdapter( onItemClick = { item -> @@ -113,7 +117,7 @@ class MyKeyboard : Fragment() { private fun loadList() { viewLifecycleOwner.lifecycleScope.launch { - loadingOverlay.show() + swipeRefresh.isRefreshing = true try { val resp = getlistByUser() if (resp?.code == 0 && resp.data != null) { @@ -125,7 +129,7 @@ class MyKeyboard : Fragment() { } catch (e: Exception) { Toast.makeText(requireContext(), "Load failed: ${e.message}", Toast.LENGTH_SHORT).show() } finally { - loadingOverlay.hide() + swipeRefresh.isRefreshing = false } } } diff --git a/app/src/main/java/com/example/myapplication/ui/mine/myotherpages/PersonalSettings.kt b/app/src/main/java/com/example/myapplication/ui/mine/myotherpages/PersonalSettings.kt index 74aea1c..046feea 100644 --- a/app/src/main/java/com/example/myapplication/ui/mine/myotherpages/PersonalSettings.kt +++ b/app/src/main/java/com/example/myapplication/ui/mine/myotherpages/PersonalSettings.kt @@ -20,6 +20,7 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.core.content.ContextCompat import androidx.core.content.FileProvider import androidx.lifecycle.lifecycleScope +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.bumptech.glide.Glide import com.example.myapplication.R import com.example.myapplication.network.ApiResponse @@ -51,6 +52,7 @@ class PersonalSettings : BottomSheetDialogFragment() { private lateinit var tvGender: TextView private lateinit var tvUserId: TextView private lateinit var loadingOverlay: LoadingOverlay + private lateinit var swipeRefresh: SwipeRefreshLayout /** * ✅ Android Photo Picker @@ -83,6 +85,8 @@ class PersonalSettings : BottomSheetDialogFragment() { // 初始化loadingOverlay loadingOverlay = LoadingOverlay.attach(requireView() as ViewGroup) + swipeRefresh = view.findViewById(R.id.swipeRefresh) + swipeRefresh.setOnRefreshListener { loadUser() } // 关闭 view.findViewById(R.id.iv_close).setOnClickListener { @@ -174,11 +178,16 @@ class PersonalSettings : BottomSheetDialogFragment() { // ===================== load & render ===================== + loadUser() + + } + + private fun loadUser() { viewLifecycleOwner.lifecycleScope.launch { - loadingOverlay.show() + swipeRefresh.isRefreshing = true try { val resp = getUserdata() - val u = resp?.data // 如果你的 ApiResponse 字段不是 data,这里改成你的字段名 + val u = resp?.data // ???????????? ApiResponse ???????????? data?????????????????????????????? if (u == null) { Toast.makeText(requireContext(), "Load failed", Toast.LENGTH_SHORT).show() return@launch @@ -186,7 +195,7 @@ class PersonalSettings : BottomSheetDialogFragment() { user = u renderUser(u) } finally { - loadingOverlay.hide() + swipeRefresh.isRefreshing = false } } } diff --git a/app/src/main/res/drawable-night/keyboard_icon_voice.png b/app/src/main/res/drawable-night/keyboard_icon_voice.png new file mode 100644 index 0000000..44834b9 Binary files /dev/null and b/app/src/main/res/drawable-night/keyboard_icon_voice.png differ diff --git a/app/src/main/res/drawable/keyboard_button_bg5.xml b/app/src/main/res/drawable/keyboard_button_bg5.xml new file mode 100644 index 0000000..62c3bab --- /dev/null +++ b/app/src/main/res/drawable/keyboard_button_bg5.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/keyboard_icon_voice_darkness.png b/app/src/main/res/drawable/keyboard_icon_voice_darkness.png new file mode 100644 index 0000000..44834b9 Binary files /dev/null and b/app/src/main/res/drawable/keyboard_icon_voice_darkness.png differ diff --git a/app/src/main/res/layout/ai_keyboard.xml b/app/src/main/res/layout/ai_keyboard.xml index a84958e..3288450 100644 --- a/app/src/main/res/layout/ai_keyboard.xml +++ b/app/src/main/res/layout/ai_keyboard.xml @@ -165,7 +165,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Clear" - android:textColor="#1B1F1A" + android:textColor="@color/ai_keyboard_button_text_color" android:textSize="13sp" /> diff --git a/app/src/main/res/layout/fragment_shop.xml b/app/src/main/res/layout/fragment_shop.xml index ed54bbb..558eeb1 100644 --- a/app/src/main/res/layout/fragment_shop.xml +++ b/app/src/main/res/layout/fragment_shop.xml @@ -198,7 +198,7 @@ diff --git a/app/src/main/res/layout/fragment_shop_style_page.xml b/app/src/main/res/layout/fragment_shop_style_page.xml index 9de6541..51d3442 100644 --- a/app/src/main/res/layout/fragment_shop_style_page.xml +++ b/app/src/main/res/layout/fragment_shop_style_page.xml @@ -3,5 +3,6 @@ android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" - android:padding="16dp" + android:paddingStart="16dp" + android:paddingEnd="16dp" android:clipToPadding="false"/> diff --git a/app/src/main/res/layout/item_ai_message.xml b/app/src/main/res/layout/item_ai_message.xml index f664318..4eda9e6 100644 --- a/app/src/main/res/layout/item_ai_message.xml +++ b/app/src/main/res/layout/item_ai_message.xml @@ -7,7 +7,7 @@ + android:background="@drawable/keyboard_button_bg5"> diff --git a/app/src/main/res/layout/item_theme_card.xml b/app/src/main/res/layout/item_theme_card.xml index 5a4701b..49b376b 100644 --- a/app/src/main/res/layout/item_theme_card.xml +++ b/app/src/main/res/layout/item_theme_card.xml @@ -11,6 +11,7 @@ + + - \ No newline at end of file + diff --git a/app/src/main/res/layout/personal_settings.xml b/app/src/main/res/layout/personal_settings.xml index 2462eb6..ceaf97a 100644 --- a/app/src/main/res/layout/personal_settings.xml +++ b/app/src/main/res/layout/personal_settings.xml @@ -8,17 +8,21 @@ android:background="#F6F7FB" tools:context=".ui.home.myotherpages.PersonalSettings"> - - + + android:layout_height="match_parent" + android:fillViewport="true" + android:overScrollMode="never"> + - - - \ No newline at end of file + + + + diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml new file mode 100644 index 0000000..c0770b6 --- /dev/null +++ b/app/src/main/res/values-night/colors.xml @@ -0,0 +1,5 @@ + + + #707070 + #FFFFFF + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index d27779c..b6a353f 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -11,4 +11,6 @@ #801B1F1A #FF1B1F1A #FF9F9F9F + #FFFFFFFF + #1B1F1A