Compare commits

...

245 Commits

Author SHA1 Message Date
Tibor Kaputa 4a071ffdb8
Update FUNDING.yml 2024-06-11 11:59:14 +02:00
Tibor Kaputa 398cccda11
Update README.md 2024-06-11 11:43:15 +02:00
Tibor Kaputa 0be61052f4
updating the f-droid icon 2023-10-05 09:19:46 +02:00
Tibor Kaputa 5a42fa5949
Merge pull request #698 from weblate/weblate-simple-mobile-tools-simple-dialer
Translations update from Hosted Weblate
2023-09-28 23:06:44 +02:00
Lionel HANNEQUIN 82d6be03f5
Translated using Weblate (French)
Currently translated at 100.0% (17 of 17 strings)

Translation: Simple Mobile Tools/Simple Dialer metadata
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer-metadata/fr/
2023-09-28 05:56:58 +02:00
Lionel HANNEQUIN d0849d14e7
Translated using Weblate (French)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/fr/
2023-09-28 05:56:58 +02:00
Lionel HANNEQUIN a79c1aaa83
Translated using Weblate (French)
Currently translated at 100.0% (17 of 17 strings)

Translation: Simple Mobile Tools/Simple Dialer metadata
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer-metadata/fr/
2023-09-27 18:07:37 +02:00
Lionel HANNEQUIN 0ac8cd4423
Translated using Weblate (French)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/fr/
2023-09-27 18:07:37 +02:00
teemue 2f28ff28ac
Translated using Weblate (Finnish)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/fi/
2023-09-25 20:03:18 +02:00
Tibor Kaputa 9f7174faf6
Merge pull request #697 from weblate/weblate-simple-mobile-tools-simple-dialer
Translations update from Hosted Weblate
2023-09-23 18:39:14 +02:00
Tibor Kaputa 3a50c7a122
Update strings.xml 2023-09-23 18:38:48 +02:00
Peter Dave Hello 888e2acf60
Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/zh_Hant/
2023-09-22 00:19:48 +02:00
Anonymous 026e5af6ad
Translated using Weblate (Odia)
Currently translated at 100.0% (0 of 0 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/or/
2023-09-21 18:10:32 +02:00
Subham Jena 610a967567
Added translation using Weblate (Odia) 2023-09-21 18:10:27 +02:00
gallegonovato be737c767f
Translated using Weblate (Spanish)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/es/
2023-09-21 11:22:20 +02:00
tibbi 15b34495c5 updating changelog 2023-09-19 16:49:43 +02:00
tibbi 277167fa0c update version to 5.18.1 2023-09-19 16:49:37 +02:00
Tibor Kaputa 90603cc005
Merge pull request #690 from weblate/weblate-simple-mobile-tools-simple-dialer
Translations update from Hosted Weblate
2023-09-19 16:38:40 +02:00
VfBFan fdb635a94a
Translated using Weblate (German)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/de/
2023-09-19 16:37:47 +02:00
VfBFan 1d42405d26
Translated using Weblate (German)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/de/
2023-09-19 16:37:47 +02:00
tibbi a55ef54e16 updating commons 2023-09-19 16:37:42 +02:00
tibbi 59e0074447 updating commons 2023-09-18 13:40:11 +02:00
Tibor Kaputa 9ac6fc2edb
Merge pull request #691 from esensar/gradle-deprecation-warnings
Clean up gradle deprecation warnings
2023-09-13 14:39:40 +02:00
Ensar Sarajčić 3bb3bf812a Clean up gradle deprecation warnings 2023-09-13 13:09:10 +02:00
Tibor Kaputa 1c80b662ec
Merge pull request #688 from fatihergin/feature/implement-contact-blocking
Feature/implement contact blocking
2023-09-11 23:07:29 +02:00
fatih ergin 4cd5529446 update simple-commons ref for contact blocking helpers 2023-09-11 23:35:30 +03:00
fatih ergin f3a04a90cf implement contact blocking 2023-09-11 21:53:35 +03:00
Tibor Kaputa 9855efcf66
Merge pull request #687 from fatihergin/fix/ISSUE-568-cannot-delete-individual-call-log-entry
refresh recent call history on individual call history item deletion too
2023-09-07 21:36:49 +02:00
fatih ergin 20a34761dd refresh recent call history on individual call history deletion too 2023-09-07 21:33:51 +03:00
Tibor Kaputa 5fbf7c2b62
Merge pull request #686 from fatihergin/feature/migrate-to-gradle-kts-version-catalog
Feature/migrate to gradle kts & version catalog
2023-09-07 08:39:40 +02:00
fatih ergin 973d0f3ac0 update simple-commons 2023-09-06 23:50:47 +03:00
fatih ergin 3959383322 migrate to gradle kts and version catalog 2023-09-06 23:44:10 +03:00
Tibor Kaputa c5b7837c49
Merge pull request #684 from weblate/weblate-simple-mobile-tools-simple-dialer
Translations update from Hosted Weblate
2023-09-05 16:28:24 +02:00
Tibor Kaputa 3195df2562
Update strings.xml 2023-09-05 16:28:16 +02:00
mimvahedi 82cdf138b5
Translated using Weblate (Persian)
Currently translated at 92.8% (65 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/fa/
2023-09-04 07:15:06 +02:00
Anonymous 1e2941592d
Translated using Weblate (Persian)
Currently translated at 100.0% (0 of 0 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/fa/
2023-09-02 16:13:23 +02:00
mimvahedi 06d41f63ff
Added translation using Weblate (Persian) 2023-09-02 16:13:08 +02:00
Tibor Kaputa 9464b76036
Merge pull request #673 from fatihergin/feature/viewbinding-sdk-34-migration
Feature/viewbinding sdk 34 migration
2023-08-29 17:49:54 +02:00
fatih ergin 2922e1caad rename ic_call_decline that conflicts with android.core internals 2023-08-25 23:01:44 +03:00
Tibor Kaputa 259c65420a
Merge pull request #661 from weblate/weblate-simple-mobile-tools-simple-dialer
Translations update from Hosted Weblate
2023-08-25 10:33:12 +02:00
Tibor Kaputa 425f6622ce
fixing a view id 2023-08-25 00:30:30 +02:00
fatih ergin 168dcc9f71 migrate fragments to viewbinding 2023-08-25 01:14:28 +03:00
fatih ergin d65d6e884d migrate dialogs to viewbinding 2023-08-25 01:14:20 +03:00
fatih ergin 81ec7fc1de migrate adapters to viewbinding 2023-08-25 01:14:11 +03:00
fatih ergin f962765108 migrate activities to viewbinding 2023-08-25 01:14:00 +03:00
fatih ergin 071a78e00a enable viewbinding
update compile sdk to 34
update kotlin version to 1.9.0
2023-08-23 20:49:07 +03:00
J. Lavoie bdb0936f5f
Translated using Weblate (Italian)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/it/
2023-08-23 15:55:01 +02:00
J. Lavoie ef09d92b85
Translated using Weblate (French)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/fr/
2023-08-23 15:55:01 +02:00
Tibor Kaputa 8b61786a63
Merge pull request #658 from weblate/weblate-simple-mobile-tools-simple-dialer
Translations update from Hosted Weblate
2023-08-22 17:22:12 +02:00
Slávek Banko 8175f59672
Translated using Weblate (Czech)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/cs/
2023-08-20 15:48:07 +02:00
tibbi e4610ce3a5 fixing a translation 2023-08-14 18:00:35 +02:00
Tibor Kaputa ef22a2c917
Merge pull request #653 from weblate/weblate-simple-mobile-tools-simple-dialer
Translations update from Hosted Weblate
2023-08-14 17:59:46 +02:00
VfBFan 4b59c96337
Translated using Weblate (German)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/de/
2023-08-05 22:48:10 +02:00
josé m ad56d6e8a6
Translated using Weblate (Galician)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/gl/
2023-08-04 15:04:54 +02:00
Tibor Kaputa a48f19ca12
Merge pull request #649 from weblate/weblate-simple-mobile-tools-simple-dialer
Translations update from Hosted Weblate
2023-07-28 08:33:26 +02:00
en2sv 430d049630
Translated using Weblate (Swedish)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/sv/
2023-07-24 10:58:55 +02:00
Tibor Kaputa f97a186366
Merge pull request #648 from Merkost/speed_dial_search
Speed dial search implemented
2023-07-24 10:58:51 +02:00
merkost b3e5847b95 Managing letter_fastscroller_thumb visibility 2023-07-24 13:27:51 +10:00
merkost c8539a114a Changed string to choose_contact 2023-07-22 23:13:57 +10:00
merkost 20e93c6065 Updated commons 2023-07-22 23:13:34 +10:00
merkost 25b15785a0 Changed MIN_COLUMNS_COUNT value to 1 and improved readability of created items in changeColumnCount 2023-07-22 23:13:12 +10:00
merkost 037e8ca9d4 Revert "Added select_contact string resource"
This reverts commit 96dfd3f230.
2023-07-22 23:07:40 +10:00
merkost b99a851064 Implemented search in SelectContactDialog 2023-07-22 12:06:31 +10:00
merkost 7f7e179d4b ContactsAdapter mutable arrayList changed to list 2023-07-22 12:03:57 +10:00
merkost 96dfd3f230 Added select_contact string resource 2023-07-22 12:01:12 +10:00
Tibor Kaputa 71a1f3342f
Merge pull request #647 from weblate/weblate-simple-mobile-tools-simple-dialer
Translations update from Hosted Weblate
2023-07-21 15:29:38 +02:00
Priit Jõerüüt e7cbb530ee
Translated using Weblate (Estonian)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/et/
2023-07-21 15:07:19 +02:00
Tibor Kaputa 90b4a2b87a
Merge pull request #644 from austenadler/master
Update mute button state outside toggleMicrophone()
2023-07-20 22:41:48 +02:00
tibbi f82169b41c updating commons 2023-07-20 09:44:14 +02:00
Tibor Kaputa 703eacc161
Merge pull request #643 from weblate/weblate-simple-mobile-tools-simple-dialer
Translations update from Hosted Weblate
2023-07-20 09:42:52 +02:00
abc0922001 9046ea0e2a
Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (16 of 16 strings)

Translation: Simple Mobile Tools/Simple Dialer metadata
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer-metadata/zh_Hant/
2023-07-20 09:42:34 +02:00
abc0922001 8de142542f
Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/zh_Hant/
2023-07-20 09:42:34 +02:00
Tibor Kaputa 44a81dc7cf
Merge pull request #639 from Merkost/grid_view_favorites
Grid view favorites
2023-07-20 09:42:29 +02:00
Tibor Kaputa 327e3a4c55
removing duplicate empty lines 2023-07-20 09:42:05 +02:00
Tibor Kaputa 0c8925f887
show column count icon when fits 2023-07-20 09:41:35 +02:00
Tibor Kaputa 59d5e92fcd
Merge pull request #645 from Merkost/manage_speed_dial_selection
Manage speed dial long press disabled
2023-07-20 09:03:15 +02:00
merkost a1d5164823 Manage speed dial long press disabled 2023-07-20 14:22:03 +10:00
merkost 7096cf5912 Added change column count animation 2023-07-20 11:41:39 +10:00
merkost 1379c288e5 Null fixes 2023-07-19 16:57:28 +10:00
merkost 532400b8f5 Improved onFontChange listener 2023-07-19 16:53:28 +10:00
merkost 5f246d6c6e Fixed font setting in Adapters 2023-07-19 16:45:30 +10:00
merkost 0e5d0154ad Refreshing menu items after view type changed 2023-07-19 16:18:46 +10:00
merkost 8051bc19e0 Merge remote-tracking branch 'origin/grid_view_favorites' into grid_view_favorites 2023-07-19 10:59:45 +10:00
merkost 04cd1db82e column_count item updated 2023-07-19 10:59:38 +10:00
Konstantin Merenkov ace7f416bf
Merge branch 'master' into grid_view_favorites 2023-07-19 10:50:34 +10:00
merkost 6a0bc60023 Fixed column_count menu item visibility 2023-07-19 10:49:53 +10:00
merkost f8e5309dec Updated simple-commons 2023-07-19 10:47:18 +10:00
merkost bcb76d39f2 Updated icon for change view menu item 2023-07-18 17:57:46 +10:00
Austen Adler 835f2ad2eb Update mute button state outside toggleMicrophone() 2023-07-17 22:07:39 -04:00
tibbi 8e7f3581b4 updating commons 2023-07-17 14:47:41 +02:00
merkost 799ad90ec2 Moved shared items to commons 2023-07-15 12:27:03 +10:00
Tibor Kaputa e226c66e16
Merge pull request #641 from weblate/weblate-simple-mobile-tools-simple-dialer
Translations update from Hosted Weblate
2023-07-14 14:38:23 +02:00
elgratea 7aa6c9c292
Translated using Weblate (Bulgarian)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/bg/
2023-07-14 14:37:50 +02:00
Tibor Kaputa 0a1eabdba5
Merge pull request #640 from spkprs/patch-14
Update.xml
2023-07-14 14:37:44 +02:00
spkprs d2d8a28c18
Update strings.xml 2023-07-14 14:33:46 +03:00
merkost e0e283cf71 Moved item contact grid to commons lib 2023-07-14 10:19:13 +10:00
merkost fe2f2e03ce item_contact_grid.xml improved 2023-07-13 23:04:14 +10:00
merkost b825eb686c Merge remote-tracking branch 'origin/grid_view_favorites' into grid_view_favorites 2023-07-13 23:03:58 +10:00
merkost c499947bc7 Merge remote-tracking branch 'origin/grid_view_favorites' into grid_view_favorites 2023-07-13 23:03:53 +10:00
merkost 9f622c9e4a Merge remote-tracking branch 'origin/grid_view_favorites' into grid_view_favorites 2023-07-13 23:03:29 +10:00
merkost d0c9daa3ce Renaming 2023-07-13 23:03:23 +10:00
merkost 2311fc4af9 Renaming 2023-07-13 23:03:08 +10:00
merkost a4130cd948 Removed slider 2023-07-13 23:02:54 +10:00
merkost e20a527527 Created column_count menu item 2023-07-13 23:02:26 +10:00
merkost 24cc3f5344 Created grid span count slider in dialog 2023-07-12 18:51:43 +10:00
merkost 2e889f2093 Implemented zoom listener to dynamically change span count 2023-07-12 18:30:03 +10:00
merkost c0037073d1 Added gridLayoutSpanCount in Config.kt 2023-07-12 18:29:02 +10:00
merkost d71b795d2f Contact name in 2 lines with ellipsize in the end 2023-07-12 13:56:15 +10:00
merkost eb775e870b Change view type setting moved up 2023-07-12 13:36:53 +10:00
merkost e8bee1445a Adapter drag support for grid 2023-07-11 12:29:01 +10:00
merkost e17555c977 Contact item improving 2023-07-11 12:28:00 +10:00
merkost dbc78642b1 Adapter improving for grid view and refactoring 2023-07-11 11:52:46 +10:00
merkost 0c0503d24f Created updateListAdapter fun for changing viewType 2023-07-11 11:52:07 +10:00
merkost 9f1f9172ae Created new grid contact view 2023-07-11 11:50:32 +10:00
merkost 7eafb4aaad Added change_view_type option in menu 2023-07-11 10:48:03 +10:00
merkost 267e5c35f0 Added ChangeViewTypeDialog 2023-07-11 10:39:07 +10:00
merkost b851c0881a Added viewType setting 2023-07-11 10:33:42 +10:00
Tibor Kaputa 0cd9341838
Merge pull request #637 from weblate/weblate-simple-mobile-tools-simple-dialer
Translations update from Hosted Weblate
2023-07-10 16:59:02 +02:00
Sergio Marques 9214f5c18b
Translated using Weblate (Portuguese)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/pt/
2023-07-10 16:58:20 +02:00
Priit Jõerüüt f6f9f6a5ff
Translated using Weblate (Estonian)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/et/
2023-07-10 16:58:20 +02:00
Dan 0807cbbf92
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/uk/
2023-07-10 16:58:20 +02:00
Rex_sa c499b8c952
Translated using Weblate (Arabic)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/ar/
2023-07-10 16:58:20 +02:00
Josep M. Ferrer 42a70047d7
Translated using Weblate (Catalan)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/ca/
2023-07-10 16:58:20 +02:00
Eric 10af0a699e
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/zh_Hans/
2023-07-10 16:58:20 +02:00
Oğuz Ersen 8c5674c790
Translated using Weblate (Turkish)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/tr/
2023-07-10 16:58:20 +02:00
Agnieszka C 6469c52926
Translated using Weblate (Polish)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/pl/
2023-07-10 16:58:20 +02:00
Guillaume 58a8a18027
Translated using Weblate (Dutch)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/nl/
2023-07-10 16:58:20 +02:00
VfBFan 3c0d166b37
Translated using Weblate (German)
Currently translated at 100.0% (70 of 70 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/de/
2023-07-10 16:58:19 +02:00
Tibor Kaputa ebdb8dcba6
Merge pull request #638 from Merkost/private_contacts_at_speed_dial
Added private numbers provider to ManageSpeedDialActivity
2023-07-10 16:58:14 +02:00
merkost b5a863aaef Added private numbers provider to ManageSpeedDialActivity and ArrayLists changed to Kotlin lists 2023-07-10 23:40:53 +10:00
Tibor Kaputa 67a8c27120
Merge pull request #633 from Merkost/call_history_export_import
Call history export import
2023-07-05 11:07:47 +02:00
Tibor Kaputa 2e8d16c703
updating the slovak translation 2023-07-05 11:07:22 +02:00
Tibor Kaputa 4cbafe1608
removing another empty line 2023-07-05 11:06:14 +02:00
Tibor Kaputa 8c67df0abd
removing another empty line 2023-07-05 11:04:51 +02:00
Tibor Kaputa c8edf9a00d
removing an empty line 2023-07-05 11:04:16 +02:00
Tibor Kaputa f24d10166d
flipping view names 2023-07-05 11:03:43 +02:00
Tibor Kaputa a2499e331a
flipping view names 2023-07-05 11:03:20 +02:00
merkost 58eb9585b4 Setup calls import and export settings handled separately 2023-07-05 18:46:47 +10:00
merkost 5e75ea700c Added proguard rules for kotlinx.serialization 2023-07-05 18:43:35 +10:00
merkost 6099e4d37b Merge remote-tracking branch 'origin/call_history_export_import' into call_history_export_import 2023-07-05 11:12:14 +10:00
merkost 0ad6fcb300 Fixed label color changing 2023-07-05 11:12:08 +10:00
merkost d8b6afe669 fixed label color changing 2023-07-05 11:08:40 +10:00
merkost aff820a84a Added kotlinx-serialization plugin 2023-07-05 11:02:32 +10:00
merkost af9ab19185 Added empty import file toast 2023-07-04 10:10:00 +10:00
merkost 3e4c5de826 Reverted item_contact_frame to ConstraintLayout 2023-07-03 11:55:27 +10:00
merkost 1309097d27 Added invalid file format toast for import 2023-07-03 11:40:38 +10:00
merkost 1c554c33fe Added ExportCallHistoryDialog 2023-07-02 23:14:20 +10:00
merkost 931a2f63d1 Exporting failed error removed if user cancelled his action on the file picker screen 2023-07-02 22:45:03 +10:00
merkost 6fc028db33 Created migration section in settings and import/export rearranged 2023-07-02 22:31:37 +10:00
merkost 3892c5f5d5 Changed runCatching to try/catch block 2023-07-02 10:13:07 +10:00
merkost 22a2fbb331 ArrayList to Kotlin List refactoring 2023-07-02 10:07:26 +10:00
merkost 7f2fa6cf7e Sort the call history before restoring, so that it is saved in the right order 2023-07-01 12:04:07 +10:00
merkost ec57e45770 Fixed a bug - for some reason FrameLayout was casted to Constraint layout 2023-07-01 12:02:59 +10:00
merkost 031b662f72 Merge branch 'master' into call_history_export_import
# Conflicts:
#	app/src/main/kotlin/com/simplemobiletools/dialer/helpers/RecentsHelper.kt
2023-07-01 11:42:26 +10:00
merkost 9061115b11 Import/Export implementing 2023-07-01 11:29:32 +10:00
merkost 54778a228e Created new items in the settings for import/export call history 2023-07-01 11:28:46 +10:00
merkost 2abc59adcd New export and import call history strings 2023-07-01 11:27:48 +10:00
merkost 1c57d5e5e2 build.gradle plugins section refactoring 2023-07-01 11:27:11 +10:00
merkost d3bff0a272 Added Serializable to RecentCall.kt and improved documentation string 2023-07-01 11:26:13 +10:00
merkost eeaa073d55 Added restoreRecentCalls in RecentsHelper.kt and changed getRecents sort to Calls.DATE 2023-07-01 11:24:36 +10:00
tibbi a23dcd5302 fixing some margins 2023-06-30 14:25:56 +02:00
tibbi 76af3f6899 show the overflow button at unknown calls too 2023-06-30 11:17:53 +02:00
tibbi f27b7c4c3c adding an empty line 2023-06-30 10:53:33 +02:00
tibbi 2ad1980abe unknown numbers can also be stored as -1, not just null 2023-06-30 10:52:03 +02:00
tibbi f2b0428679 use the newer contact thumbnail layout 2023-06-30 10:27:17 +02:00
tibbi 7b80aa1b9f updating commons 2023-06-29 14:49:47 +02:00
Tibor Kaputa d2fefd9e03
Merge pull request #631 from Merkost/master
Fixed gsm code calling
2023-06-29 14:49:18 +02:00
merkost 4a4e26d6d7 Fixed gsm code calling 2023-06-29 19:35:04 +10:00
Tibor Kaputa 151dcea56e
Merge pull request #629 from Merkost/showing_unknown_callers
Added unknown phone calls visibility in Call History
2023-06-28 09:45:04 +02:00
Tibor Kaputa e918621fa4
Merge pull request #630 from Merkost/block_hidden_numbers_feature
Added blocking calls from hidden numbers
2023-06-27 17:30:02 +02:00
tibbi b7703457bc updating commons 2023-06-23 10:09:57 +02:00
merkost cedcd6e304 Added blocking calls from hidden numbers 2023-06-23 14:25:23 +10:00
tibbi fbe4868586 Merge branch 'master' of github.com:SimpleMobileTools/Simple-Dialer 2023-06-22 23:57:19 +02:00
tibbi 193cb76358 replacing jcenter with mavenCentral 2023-06-22 23:57:08 +02:00
merkost e0b0aac5fb Fixed typo in a word 2023-06-21 21:55:44 +10:00
merkost d575123474 Added unknown phone calls visibility in Call History 2023-06-21 10:54:16 +10:00
Tibor Kaputa c0642f3cf5
Merge pull request #628 from Merkost/recent_calls_loading
Improved RecentCallsAdapter for onScroll loading
2023-06-20 13:44:18 +02:00
Tibor Kaputa 571aeec977
optimizing imports 2023-06-20 13:43:58 +02:00
merkost 939cba30ea Improved RecentCallsAdapter for onScroll loading 2023-06-20 14:08:10 +10:00
tibbi 56d0a0ca07 extending changelogs 2023-06-08 17:33:13 +02:00
tibbi d7b412efe7 updating changelog 2023-06-08 17:31:45 +02:00
tibbi eb6dc3a9cc update version to 5.18.0 2023-06-08 17:31:38 +02:00
tibbi 0d2bc71e79 use proper status bar color at call screen with Material You theme 2023-06-08 17:18:40 +02:00
Tibor Kaputa 4df23346d3
Merge pull request #623 from Merkost/speed_dial_numbers_fix
Fixed speed dial when contact has multiple phone numbers
2023-06-08 16:56:54 +02:00
Tibor Kaputa 50f16ba1d1
Update SpeedDialAdapter.kt 2023-06-08 16:56:15 +02:00
Tibor Kaputa 6bf4f6bc16
Delete item_phone_number.xml 2023-06-08 16:55:46 +02:00
Tibor Kaputa e5b5a55b57
Delete PhonesAdapter.kt 2023-06-08 16:55:39 +02:00
merkost 0e703c2942 Added selected number visibility in dialog 2023-06-08 13:14:48 +10:00
merkost 2aa07c54e5 Deleted showing number with the name in ManageSpeedDial screen 2023-06-08 13:10:09 +10:00
merkost 444ac03727 Changed custom dialog to RadioGroupDialog 2023-06-08 13:06:57 +10:00
tibbi 59d850922d fix #598, properly display organization contact names 2023-06-07 20:57:56 +02:00
Tibor Kaputa fbce7496c4
Merge pull request #622 from weblate/weblate-simple-mobile-tools-simple-dialer
Translations update from Hosted Weblate
2023-06-07 20:40:15 +02:00
Tibor Kaputa a091e48f3f
Update strings.xml 2023-06-07 20:39:58 +02:00
merkost a9c2d752ce Fixed speed dial when contact has multiple phone numbers 2023-06-03 12:20:16 +10:00
ngocanhtve 18c35af83c
Translated using Weblate (Vietnamese)
Currently translated at 100.0% (68 of 68 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/vi/
2023-05-30 12:16:50 +02:00
Milo Ivir 353695f74b
Translated using Weblate (Croatian)
Currently translated at 100.0% (68 of 68 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/hr/
2023-05-30 12:16:50 +02:00
ngocanhtve 80082f6780
Translated using Weblate (Vietnamese)
Currently translated at 2.9% (2 of 68 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/vi/
2023-05-30 12:16:50 +02:00
Anonymous fa0ac1df5c
Translated using Weblate (Vietnamese)
Currently translated at 100.0% (0 of 0 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/vi/
2023-05-30 12:16:50 +02:00
ngocanhtve 60a95d9624
Added translation using Weblate (Vietnamese) 2023-05-30 12:16:50 +02:00
tibbi 4b281635c2 updating commons, related to #598 2023-05-30 12:16:42 +02:00
Tibor Kaputa c63056e422
Merge pull request #619 from liyamahendra/master
refactor: update Simple-Commons hash
2023-05-24 10:07:32 +02:00
Mahendra Liya c543cc785b refactor: update Simple-Commons hash 2023-05-23 22:15:11 +05:30
Tibor Kaputa 42766f0dad
Merge pull request #612 from liyamahendra/master
fix: issue #574
2023-05-18 12:23:01 +02:00
Mahendra Liya 8889939b60 fix: issue #574 2023-05-18 15:32:05 +05:30
tibbi 1ff3c56c85 updating commons 2023-05-13 12:26:37 +02:00
Tibor Kaputa f4eae8f638
Merge pull request #593 from Amir-yazdanmanesh/master
fix a bug related to handling two SIM cards with the same name.
2023-05-13 12:19:47 +02:00
Tibor Kaputa 01467bde81
minor code style update 2023-05-13 12:19:24 +02:00
Tibor Kaputa f34379405d
adding brackets 2023-05-13 12:18:06 +02:00
Tibor Kaputa b2c5b44e61
Merge pull request #606 from Aga-C/fix-confirmation-dialog-string
Fixed remove all call history confirmation dialog string (#604)
2023-05-13 12:06:37 +02:00
Tibor Kaputa 89dc42efd4
Merge pull request #609 from weblate/weblate-simple-mobile-tools-simple-dialer
Translations update from Hosted Weblate
2023-05-13 12:06:31 +02:00
Guillaume 22dd4bf8f8
Translated using Weblate (Dutch)
Currently translated at 100.0% (68 of 68 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/nl/
2023-05-12 15:51:15 +02:00
Tibor Kaputa d03461f9af
Merge pull request #607 from weblate/weblate-simple-mobile-tools-simple-dialer
Translations update from Hosted Weblate
2023-05-10 22:25:52 +02:00
Макар Разин a00a3b6594
Translated using Weblate (Belarusian)
Currently translated at 100.0% (68 of 68 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/be/
2023-05-10 22:25:31 +02:00
Agnieszka C 105bc33a53 Fixed remove all call history confirmation dialog string (#604) 2023-05-10 13:28:33 +02:00
tibbi 74b228d147 updating commons 2023-05-07 18:51:21 +02:00
am.yazdanmanesh 83553387b7 Merge remote-tracking branch 'origin/master' 2023-04-26 10:10:04 +03:30
am.yazdanmanesh ab5cd206c7 Pull last version and fix bugs 2023-04-26 10:09:51 +03:30
am.yazdanmanesh 2e0e658ef0 Pull last version and fix bugs 2023-04-26 09:37:14 +03:30
AmirMohammad Yazdanmanesh 515590c69d
Merge branch 'SimpleMobileTools:master' into master 2023-04-22 18:36:29 +03:30
tibbi 5a9de64ccd updating changelog 2023-04-19 16:16:12 +02:00
tibbi fbed6e85ed update version to 5.17.8 2023-04-19 16:16:05 +02:00
tibbi 52645539f7 updating commons 2023-04-19 16:06:10 +02:00
Tibor Kaputa 08d09bc18a
Merge pull request #590 from ismailnurudeen/fix/contacts-without-num
fix: prevent showing of contacts without phone numbers.
2023-04-19 16:05:47 +02:00
Tibor Kaputa 79407efbb2
Merge pull request #588 from ismailnurudeen/fix/dialer-issues
Fix/dialer shortcut & call confirmation dialog
2023-04-19 16:04:14 +02:00
ismailnurudeen e2455d8cf0 fix: always dial primary number by default 2023-04-18 18:06:34 +01:00
ismailnurudeen c12a4c18db fix: formatting 2023-04-18 16:58:48 +01:00
ismailnurudeen 7c17cf5dcd Merge branch 'master' into fix/contacts-without-num
# Conflicts:
#	app/src/main/kotlin/com/simplemobiletools/dialer/fragments/FavoritesFragment.kt
2023-04-18 16:57:51 +01:00
Tibor Kaputa 0fb7d4dbe7
Merge pull request #589 from ismailnurudeen/fix/favourite-private-contacts
fix: show favourite private contacts
2023-04-18 15:41:45 +02:00
ismailnurudeen 725a8c41e4 fix: prevent showing of contacts without phone numbers. 2023-04-16 17:34:19 +01:00
ismailnurudeen b0454de90f fix: show favourite private contacts 2023-04-16 09:50:08 +01:00
ismailnurudeen 87afcc86b1 fix: dialpad call confirmation 2023-04-15 11:11:53 +01:00
ismailnurudeen f172826116 fix: shortcut using wrong number 2023-04-15 11:06:24 +01:00
tibbi 8fa124680a updating changelog 2023-04-12 14:45:40 +02:00
tibbi 9cd02ff987 update version to 5.17.7 2023-04-12 14:45:34 +02:00
tibbi bb048a4d33 fix #582, fixing a dialpad crash 2023-04-12 14:42:33 +02:00
tibbi d16c3183f2 updating changelog 2023-04-07 18:15:09 +02:00
tibbi 526cac4fed update version to 5.17.6 2023-04-07 18:15:02 +02:00
tibbi 6039c591ff adding a null check 2023-04-07 18:10:36 +02:00
tibbi 846f668d59 avoid showing contacts without phone numbers at the dialpad 2023-04-07 18:09:45 +02:00
tibbi 7730baff13 updating commons 2023-04-07 18:03:01 +02:00
Tibor Kaputa fde79e8558
Merge pull request #571 from weblate/weblate-simple-mobile-tools-simple-dialer
Translations update from Hosted Weblate
2023-04-07 15:38:58 +02:00
Slávek Banko 7e7981509a
Translated using Weblate (Czech)
Currently translated at 100.0% (68 of 68 strings)

Translation: Simple Mobile Tools/Simple Dialer
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-dialer/cs/
2023-04-07 15:38:35 +02:00
Tibor Kaputa 202f14dffa
Merge pull request #576 from ismailnurudeen/fix/dtmf-tone-handling
fix: Remove dialpadBeeps check for DTMF tone handling
2023-04-07 15:38:31 +02:00
ismailnurudeen 236003c5d7 fix: Remove dialpadBeeps check for DTMF tone handling 2023-04-07 12:28:16 +01:00
am.yazdanmanesh 5cca5b51a4 Fix dual simcard with same label bug 2022-12-23 17:26:54 +03:30
113 changed files with 2731 additions and 1240 deletions

2
.github/FUNDING.yml vendored
View File

@ -1,3 +1,3 @@
github: [tibbi]
patreon: tiborkaputa
custom: ["https://www.paypal.com/paypalme/simplemobiletools", "https://www.simplemobiletools.com/donate"]
custom: ["https://www.paypal.me/simplemobiletools"]

View File

@ -1,6 +1,41 @@
Changelog
==========
Version 5.18.1 *(2023-09-19)*
----------------------------
* Allow blocking contacts easier
* Added a grid view to favorites
* Added blocking calls from hidden numbers
* Added some stability, translation and UX improvements
Version 5.18.0 *(2023-06-08)*
----------------------------
* Fixed the inability of setting the app as default for handling calls on some devices
* Fixed some issues with incoming calls not being shown sometimes
* Improved speed dial handling at contacts with multiple numbers
* Properly display organization contact names
* Added some stability, translation and UX improvements
Version 5.17.8 *(2023-04-19)*
----------------------------
* Avoid showing contacts without a phone number
* Fixed multiple contact handling related glitches
* Added some stability, translation and UX improvements
Version 5.17.7 *(2023-04-12)*
----------------------------
* Added some stability, translation and UX improvements
Version 5.17.6 *(2023-04-07)*
----------------------------
* Fixed number presses during call
* Added some stability, translation and UX improvements
Version 5.17.5 *(2023-03-29)*
----------------------------

View File

@ -17,20 +17,17 @@ It comes with material design and dark theme by default, provides great user exp
Contains no ads or unnecessary permissions. It is fully opensource, provides customizable colors. Keeping track of call logs for different phone number is also a plus point of this app.
Check out the full suite of Simple Tools here:
https://www.simplemobiletools.com
<a href="https://f-droid.org/packages/com.simplemobiletools.dialer">Get it on F-Droid</a>
Facebook:
https://www.facebook.com/simplemobiletools
Reddit:
https://www.reddit.com/r/SimpleMobileTools
Telegram:
https://t.me/SimpleMobileTools
<a href='https://play.google.com/store/apps/details?id=com.simplemobiletools.dialer'><img src='https://simplemobiletools.com/images/button-google-play.svg' alt='Get it on Google Play' height='45' /></a>
<a href='https://f-droid.org/packages/com.simplemobiletools.dialer'><img src='https://simplemobiletools.com/images/button-f-droid.png' alt='Get it on F-Droid' height='45' /></a>
Support us:
IBAN: SK4083300000002000965231
Bitcoin: 19Hc8A7sWGud8sP19VXDC5a5j28UyJfpyJ
Ethereum: 0xB7a2DD6f2408Bce77334655CF5E7639aE31feb30
Litecoin: LYACbHTKaM9ZubKQGxJ4NRyVy1gHUuztRP
Bitcoin Cash: qz6dvmhq5vzkcsypxpp2mnur30muxdah4gvulx3y85
Tether: 0x250f9cC32863E59b87037a14955Ed64F879653F0
<a href="https://paypal.me/SimpleMobileTools?country.x=SK&locale.x=en_US">PayPal</a>
<a href="https://www.patreon.com/tiborkaputa">Patreon</a>
<div style="display:flex;">
<img alt="App image" src="fastlane/metadata/android/en-US/images/phoneScreenshots/1_en-US.jpeg" width="30%">

View File

@ -1,68 +0,0 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
compileSdkVersion 33
defaultConfig {
applicationId "com.simplemobiletools.dialer"
minSdkVersion 23
targetSdkVersion 33
versionCode 52
versionName "5.17.5"
setProperty("archivesBaseName", "dialer")
}
signingConfigs {
if (keystorePropertiesFile.exists()) {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
}
buildTypes {
debug {
applicationIdSuffix ".debug"
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
if (keystorePropertiesFile.exists()) {
signingConfig signingConfigs.release
}
}
}
flavorDimensions "variants"
productFlavors {
core {}
fdroid {}
prepaid {}
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lintOptions {
checkReleaseBuilds false
abortOnError false
}
}
dependencies {
implementation 'com.github.SimpleMobileTools:Simple-Commons:469df84c87'
implementation 'com.github.tibbi:IndicatorFastScroll:4524cd0b61'
implementation 'me.grantland:autofittextview:0.2.1'
}

99
app/build.gradle.kts Normal file
View File

@ -0,0 +1,99 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.konan.properties.Properties
import java.io.FileInputStream
plugins {
alias(libs.plugins.android)
alias(libs.plugins.kotlinAndroid)
alias(libs.plugins.kotlinSerialization)
base
}
base {
archivesName.set("dialer")
}
val keystorePropertiesFile: File = rootProject.file("keystore.properties")
val keystoreProperties = Properties()
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
}
android {
compileSdk = project.libs.versions.app.build.compileSDKVersion.get().toInt()
defaultConfig {
applicationId = libs.versions.app.version.appId.get()
minSdk = project.libs.versions.app.build.minimumSDK.get().toInt()
targetSdk = project.libs.versions.app.build.targetSDK.get().toInt()
versionName = project.libs.versions.app.version.versionName.get()
versionCode = project.libs.versions.app.version.versionCode.get().toInt()
}
signingConfigs {
if (keystorePropertiesFile.exists()) {
register("release") {
keyAlias = keystoreProperties.getProperty("keyAlias")
keyPassword = keystoreProperties.getProperty("keyPassword")
storeFile = file(keystoreProperties.getProperty("storeFile"))
storePassword = keystoreProperties.getProperty("storePassword")
}
}
}
buildFeatures {
viewBinding = true
buildConfig = true
}
buildTypes {
debug {
applicationIdSuffix = ".debug"
}
release {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
if (keystorePropertiesFile.exists()) {
signingConfig = signingConfigs.getByName("release")
}
}
}
flavorDimensions.add("variants")
productFlavors {
register("core")
register("fdroid")
register("prepaid")
}
sourceSets {
getByName("main").java.srcDirs("src/main/kotlin")
}
compileOptions {
val currentJavaVersionFromLibs = JavaVersion.valueOf(libs.versions.app.build.javaVersion.get().toString())
sourceCompatibility = currentJavaVersionFromLibs
targetCompatibility = currentJavaVersionFromLibs
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = project.libs.versions.app.build.kotlinJVMTarget.get()
}
namespace = libs.versions.app.version.appId.get()
lint {
checkReleaseBuilds = false
abortOnError = false
}
}
dependencies {
implementation(libs.simple.tools.commons)
implementation(libs.indicator.fast.scroll)
implementation(libs.autofit.text.view)
implementation(libs.kotlinx.serialization.json)
}

View File

@ -0,0 +1,23 @@
# Keep `Companion` object fields of serializable classes.
# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects.
-if @kotlinx.serialization.Serializable class **
-keepclassmembers class <1> {
static <1>$Companion Companion;
}
# Keep `serializer()` on companion objects (both default and named) of serializable classes.
-if @kotlinx.serialization.Serializable class ** {
static **$* *;
}
-keepclassmembers class <2>$<3> {
kotlinx.serialization.KSerializer serializer(...);
}
# Keep `INSTANCE.serializer()` of serializable objects.
-if @kotlinx.serialization.Serializable class ** {
public static ** INSTANCE;
}
-keepclassmembers class <1> {
public static <1> INSTANCE;
kotlinx.serialization.KSerializer serializer(...);
}

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.simplemobiletools.dialer"
android:installLocation="auto">
<uses-permission android:name="android.permission.READ_CONTACTS" />
@ -42,6 +41,7 @@
android:appCategory="productivity"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_launcher_name"
android:localeConfig="@xml/locale_config"
android:roundIcon="@mipmap/ic_launcher"
android:theme="@style/AppTheme">
@ -81,7 +81,8 @@
android:configChanges="orientation"
android:exported="false"
android:label="@string/blocked_numbers"
android:parentActivityName=".activities.SettingsActivity" />
android:parentActivityName=".activities.SettingsActivity"
tools:replace="android:label" />
<activity
android:name=".activities.ManageSpeedDialActivity"

View File

@ -26,13 +26,12 @@ import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.SimpleListItem
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.databinding.ActivityCallBinding
import com.simplemobiletools.dialer.dialogs.DynamicBottomSheetChooserDialog
import com.simplemobiletools.dialer.extensions.*
import com.simplemobiletools.dialer.helpers.*
import com.simplemobiletools.dialer.models.AudioRoute
import com.simplemobiletools.dialer.models.CallContact
import kotlinx.android.synthetic.main.activity_call.*
import kotlinx.android.synthetic.main.dialpad.*
import kotlin.math.max
import kotlin.math.min
@ -45,6 +44,8 @@ class CallActivity : SimpleActivity() {
}
}
private val binding by viewBinding(ActivityCallBinding::inflate)
private var isSpeakerOn = false
private var isMicrophoneOff = false
private var isCallEnded = false
@ -63,14 +64,14 @@ class CallActivity : SimpleActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_call)
setContentView(binding.root)
if (CallManager.getPhoneState() == NoCall) {
finish()
return
}
updateTextColors(call_holder)
updateTextColors(binding.callHolder)
initButtons()
audioManager.mode = AudioManager.MODE_IN_CALL
addLockScreenFlags()
@ -87,6 +88,10 @@ class CallActivity : SimpleActivity() {
super.onResume()
updateState()
updateNavigationBarColor(getProperBackgroundColor())
if (config.isUsingSystemTheme) {
updateStatusbarColor(getProperBackgroundColor())
}
}
override fun onDestroy() {
@ -100,7 +105,7 @@ class CallActivity : SimpleActivity() {
}
override fun onBackPressed() {
if (dialpad_wrapper.isVisible()) {
if (binding.dialpadWrapper.isVisible()) {
hideDialpad()
return
} else {
@ -113,119 +118,121 @@ class CallActivity : SimpleActivity() {
}
}
private fun initButtons() {
private fun initButtons() = binding.apply {
if (config.disableSwipeToAnswer) {
call_draggable.beGone()
call_draggable_background.beGone()
call_left_arrow.beGone()
call_right_arrow.beGone()
callDraggable.beGone()
callDraggableBackground.beGone()
callLeftArrow.beGone()
callRightArrow.beGone()
call_decline.setOnClickListener {
callDecline.setOnClickListener {
endCall()
}
call_accept.setOnClickListener {
callAccept.setOnClickListener {
acceptCall()
}
} else {
handleSwipe()
}
call_toggle_microphone.setOnClickListener {
callToggleMicrophone.setOnClickListener {
toggleMicrophone()
}
call_toggle_speaker.setOnClickListener {
callToggleSpeaker.setOnClickListener {
changeCallAudioRoute()
}
call_dialpad.setOnClickListener {
callDialpad.setOnClickListener {
toggleDialpadVisibility()
}
dialpad_close.setOnClickListener {
dialpadClose.setOnClickListener {
hideDialpad()
}
call_toggle_hold.setOnClickListener {
callToggleHold.setOnClickListener {
toggleHold()
}
call_add.setOnClickListener {
callAdd.setOnClickListener {
Intent(applicationContext, DialpadActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
startActivity(this)
}
}
call_swap.setOnClickListener {
callSwap.setOnClickListener {
CallManager.swap()
}
call_merge.setOnClickListener {
callMerge.setOnClickListener {
CallManager.merge()
}
call_manage.setOnClickListener {
startActivity(Intent(this, ConferenceActivity::class.java))
callManage.setOnClickListener {
startActivity(Intent(this@CallActivity, ConferenceActivity::class.java))
}
call_end.setOnClickListener {
callEnd.setOnClickListener {
endCall()
}
dialpad_0_holder.setOnClickListener { dialpadPressed('0') }
dialpad_1_holder.setOnClickListener { dialpadPressed('1') }
dialpad_2_holder.setOnClickListener { dialpadPressed('2') }
dialpad_3_holder.setOnClickListener { dialpadPressed('3') }
dialpad_4_holder.setOnClickListener { dialpadPressed('4') }
dialpad_5_holder.setOnClickListener { dialpadPressed('5') }
dialpad_6_holder.setOnClickListener { dialpadPressed('6') }
dialpad_7_holder.setOnClickListener { dialpadPressed('7') }
dialpad_8_holder.setOnClickListener { dialpadPressed('8') }
dialpad_9_holder.setOnClickListener { dialpadPressed('9') }
dialpadInclude.apply {
dialpad0Holder.setOnClickListener { dialpadPressed('0') }
dialpad1Holder.setOnClickListener { dialpadPressed('1') }
dialpad2Holder.setOnClickListener { dialpadPressed('2') }
dialpad3Holder.setOnClickListener { dialpadPressed('3') }
dialpad4Holder.setOnClickListener { dialpadPressed('4') }
dialpad5Holder.setOnClickListener { dialpadPressed('5') }
dialpad6Holder.setOnClickListener { dialpadPressed('6') }
dialpad7Holder.setOnClickListener { dialpadPressed('7') }
dialpad8Holder.setOnClickListener { dialpadPressed('8') }
dialpad9Holder.setOnClickListener { dialpadPressed('9') }
arrayOf(
dialpad_0_holder,
dialpad_1_holder,
dialpad_2_holder,
dialpad_3_holder,
dialpad_4_holder,
dialpad_5_holder,
dialpad_6_holder,
dialpad_7_holder,
dialpad_8_holder,
dialpad_9_holder,
dialpad_plus_holder,
dialpad_asterisk_holder,
dialpad_hashtag_holder
).forEach {
it.background = ResourcesCompat.getDrawable(resources, R.drawable.pill_background, theme)
it.background?.alpha = LOWER_ALPHA_INT
arrayOf(
dialpad0Holder,
dialpad1Holder,
dialpad2Holder,
dialpad3Holder,
dialpad4Holder,
dialpad5Holder,
dialpad6Holder,
dialpad7Holder,
dialpad8Holder,
dialpad9Holder,
dialpadPlusHolder,
dialpadAsteriskHolder,
dialpadHashtagHolder
).forEach {
it.background = ResourcesCompat.getDrawable(resources, R.drawable.pill_background, theme)
it.background?.alpha = LOWER_ALPHA_INT
}
dialpad0Holder.setOnLongClickListener { dialpadPressed('+'); true }
dialpadAsteriskHolder.setOnClickListener { dialpadPressed('*') }
dialpadHashtagHolder.setOnClickListener { dialpadPressed('#') }
}
dialpad_0_holder.setOnLongClickListener { dialpadPressed('+'); true }
dialpad_asterisk_holder.setOnClickListener { dialpadPressed('*') }
dialpad_hashtag_holder.setOnClickListener { dialpadPressed('#') }
dialpad_wrapper.setBackgroundColor(getProperBackgroundColor())
arrayOf(dialpad_close, call_sim_image).forEach {
dialpadWrapper.setBackgroundColor(getProperBackgroundColor())
arrayOf(dialpadClose, callSimImage).forEach {
it.applyColorFilter(getProperTextColor())
}
val bgColor = getProperBackgroundColor()
val inactiveColor = getInactiveButtonColor()
arrayOf(
call_toggle_microphone, call_toggle_speaker, call_dialpad,
call_toggle_hold, call_add, call_swap, call_merge, call_manage
callToggleMicrophone, callToggleSpeaker, callDialpad,
callToggleHold, callAdd, callSwap, callMerge, callManage
).forEach {
it.applyColorFilter(bgColor.getContrastColor())
it.background.applyColorFilter(inactiveColor)
}
arrayOf(
call_toggle_microphone, call_toggle_speaker, call_dialpad,
call_toggle_hold, call_add, call_swap, call_merge, call_manage
callToggleMicrophone, callToggleSpeaker, callDialpad,
callToggleHold, callAdd, callSwap, callMerge, callManage
).forEach { imageView ->
imageView.setOnLongClickListener {
if (!imageView.contentDescription.isNullOrEmpty()) {
@ -235,16 +242,16 @@ class CallActivity : SimpleActivity() {
}
}
call_sim_id.setTextColor(getProperTextColor().getContrastColor())
dialpad_input.disableKeyboard()
callSimId.setTextColor(getProperTextColor().getContrastColor())
dialpadInput.disableKeyboard()
dialpad_wrapper.onGlobalLayout {
dialpadHeight = dialpad_wrapper.height.toFloat()
dialpadWrapper.onGlobalLayout {
dialpadHeight = dialpadWrapper.height.toFloat()
}
}
@SuppressLint("ClickableViewAccessibility")
private fun handleSwipe() {
private fun handleSwipe() = binding.apply {
var minDragX = 0f
var maxDragX = 0f
var initialDraggableX = 0f
@ -258,84 +265,85 @@ class CallActivity : SimpleActivity() {
var rightArrowTranslation = 0f
val isRtl = isRTLLayout
call_accept.onGlobalLayout {
callAccept.onGlobalLayout {
minDragX = if (isRtl) {
call_accept.left.toFloat()
callAccept.left.toFloat()
} else {
call_decline.left.toFloat()
callDecline.left.toFloat()
}
maxDragX = if (isRtl) {
call_decline.left.toFloat()
callDecline.left.toFloat()
} else {
call_accept.left.toFloat()
callAccept.left.toFloat()
}
initialDraggableX = call_draggable.left.toFloat()
initialLeftArrowX = call_left_arrow.x
initialRightArrowX = call_right_arrow.x
initialLeftArrowScaleX = call_left_arrow.scaleX
initialLeftArrowScaleY = call_left_arrow.scaleY
initialRightArrowScaleX = call_right_arrow.scaleX
initialRightArrowScaleY = call_right_arrow.scaleY
initialDraggableX = callDraggable.left.toFloat()
initialLeftArrowX = callLeftArrow.x
initialRightArrowX = callRightArrow.x
initialLeftArrowScaleX = callLeftArrow.scaleX
initialLeftArrowScaleY = callLeftArrow.scaleY
initialRightArrowScaleX = callRightArrow.scaleX
initialRightArrowScaleY = callRightArrow.scaleY
leftArrowTranslation = if (isRtl) {
call_accept.x
callAccept.x
} else {
-call_decline.x
-callDecline.x
}
rightArrowTranslation = if (isRtl) {
-call_accept.x
-callAccept.x
} else {
call_decline.x
callDecline.x
}
if (isRtl) {
call_left_arrow.setImageResource(R.drawable.ic_chevron_right_vector)
call_right_arrow.setImageResource(R.drawable.ic_chevron_left_vector)
callLeftArrow.setImageResource(R.drawable.ic_chevron_right_vector)
callRightArrow.setImageResource(R.drawable.ic_chevron_left_vector)
}
call_left_arrow.applyColorFilter(getColor(R.color.md_red_400))
call_right_arrow.applyColorFilter(getColor(R.color.md_green_400))
callLeftArrow.applyColorFilter(getColor(R.color.md_red_400))
callRightArrow.applyColorFilter(getColor(R.color.md_green_400))
startArrowAnimation(call_left_arrow, initialLeftArrowX, initialLeftArrowScaleX, initialLeftArrowScaleY, leftArrowTranslation)
startArrowAnimation(call_right_arrow, initialRightArrowX, initialRightArrowScaleX, initialRightArrowScaleY, rightArrowTranslation)
startArrowAnimation(callLeftArrow, initialLeftArrowX, initialLeftArrowScaleX, initialLeftArrowScaleY, leftArrowTranslation)
startArrowAnimation(callRightArrow, initialRightArrowX, initialRightArrowScaleX, initialRightArrowScaleY, rightArrowTranslation)
}
call_draggable.drawable.mutate().setTint(getProperTextColor())
call_draggable_background.drawable.mutate().setTint(getProperTextColor())
callDraggable.drawable.mutate().setTint(getProperTextColor())
callDraggableBackground.drawable.mutate().setTint(getProperTextColor())
var lock = false
call_draggable.setOnTouchListener { _, event ->
callDraggable.setOnTouchListener { _, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
dragDownX = event.x
call_draggable_background.animate().alpha(0f)
callDraggableBackground.animate().alpha(0f)
stopAnimation = true
call_left_arrow.animate().alpha(0f)
call_right_arrow.animate().alpha(0f)
callLeftArrow.animate().alpha(0f)
callRightArrow.animate().alpha(0f)
lock = false
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
dragDownX = 0f
call_draggable.animate().x(initialDraggableX).withEndAction {
call_draggable_background.animate().alpha(0.2f)
callDraggable.animate().x(initialDraggableX).withEndAction {
callDraggableBackground.animate().alpha(0.2f)
}
call_draggable.setImageDrawable(getDrawable(R.drawable.ic_phone_down_vector))
call_draggable.drawable.mutate().setTint(getProperTextColor())
call_left_arrow.animate().alpha(1f)
call_right_arrow.animate().alpha(1f)
callDraggable.setImageDrawable(getDrawable(R.drawable.ic_phone_down_vector))
callDraggable.drawable.mutate().setTint(getProperTextColor())
callLeftArrow.animate().alpha(1f)
callRightArrow.animate().alpha(1f)
stopAnimation = false
startArrowAnimation(call_left_arrow, initialLeftArrowX, initialLeftArrowScaleX, initialLeftArrowScaleY, leftArrowTranslation)
startArrowAnimation(call_right_arrow, initialRightArrowX, initialRightArrowScaleX, initialRightArrowScaleY, rightArrowTranslation)
startArrowAnimation(callLeftArrow, initialLeftArrowX, initialLeftArrowScaleX, initialLeftArrowScaleY, leftArrowTranslation)
startArrowAnimation(callRightArrow, initialRightArrowX, initialRightArrowScaleX, initialRightArrowScaleY, rightArrowTranslation)
}
MotionEvent.ACTION_MOVE -> {
call_draggable.x = min(maxDragX, max(minDragX, event.rawX - dragDownX))
callDraggable.x = min(maxDragX, max(minDragX, event.rawX - dragDownX))
when {
call_draggable.x >= maxDragX - 50f -> {
callDraggable.x >= maxDragX - 50f -> {
if (!lock) {
lock = true
call_draggable.performHapticFeedback()
callDraggable.performHapticFeedback()
if (isRtl) {
endCall()
} else {
@ -343,10 +351,11 @@ class CallActivity : SimpleActivity() {
}
}
}
call_draggable.x <= minDragX + 50f -> {
callDraggable.x <= minDragX + 50f -> {
if (!lock) {
lock = true
call_draggable.performHapticFeedback()
callDraggable.performHapticFeedback()
if (isRtl) {
acceptCall()
} else {
@ -354,23 +363,25 @@ class CallActivity : SimpleActivity() {
}
}
}
call_draggable.x > initialDraggableX -> {
callDraggable.x > initialDraggableX -> {
lock = false
val drawableRes = if (isRtl) {
R.drawable.ic_phone_down_red_vector
} else {
R.drawable.ic_phone_green_vector
}
call_draggable.setImageDrawable(getDrawable(drawableRes))
callDraggable.setImageDrawable(getDrawable(drawableRes))
}
call_draggable.x <= initialDraggableX -> {
callDraggable.x <= initialDraggableX -> {
lock = false
val drawableRes = if (isRtl) {
R.drawable.ic_phone_green_vector
} else {
R.drawable.ic_phone_down_red_vector
}
call_draggable.setImageDrawable(getDrawable(drawableRes))
callDraggable.setImageDrawable(getDrawable(drawableRes))
}
}
}
@ -400,8 +411,8 @@ class CallActivity : SimpleActivity() {
}
private fun dialpadPressed(char: Char) {
CallManager.keypad(this, char)
dialpad_input.addCharacter(char)
CallManager.keypad(char)
binding.dialpadInput.addCharacter(char)
}
private fun changeCallAudioRoute() {
@ -440,9 +451,12 @@ class CallActivity : SimpleActivity() {
private fun updateCallAudioState(route: AudioRoute?) {
if (route != null) {
isMicrophoneOff = audioManager.isMicrophoneMute
updateMicrophoneButton()
isSpeakerOn = route == AudioRoute.SPEAKER
val supportedAudioRoutes = CallManager.getSupportedAudioRoutes()
call_toggle_speaker.apply {
binding.callToggleSpeaker.apply {
val bluetoothConnected = supportedAudioRoutes.contains(AudioRoute.BLUETOOTH)
contentDescription = if (bluetoothConnected) {
getString(R.string.choose_audio_route)
@ -456,7 +470,7 @@ class CallActivity : SimpleActivity() {
setImageResource(route.iconRes)
}
}
toggleButtonColor(call_toggle_speaker, enabled = route != AudioRoute.EARPIECE && route != AudioRoute.WIRED_HEADSET)
toggleButtonColor(binding.callToggleSpeaker, enabled = route != AudioRoute.EARPIECE && route != AudioRoute.WIRED_HEADSET)
createOrUpdateAudioRouteChooser(supportedAudioRoutes, create = false)
if (isSpeakerOn) {
@ -469,22 +483,26 @@ class CallActivity : SimpleActivity() {
private fun toggleMicrophone() {
isMicrophoneOff = !isMicrophoneOff
toggleButtonColor(call_toggle_microphone, isMicrophoneOff)
audioManager.isMicrophoneMute = isMicrophoneOff
CallManager.inCallService?.setMuted(isMicrophoneOff)
call_toggle_microphone.contentDescription = getString(if (isMicrophoneOff) R.string.turn_microphone_on else R.string.turn_microphone_off)
updateMicrophoneButton()
}
private fun updateMicrophoneButton() {
toggleButtonColor(binding.callToggleMicrophone, isMicrophoneOff)
binding.callToggleMicrophone.contentDescription = getString(if (isMicrophoneOff) R.string.turn_microphone_on else R.string.turn_microphone_off)
}
private fun toggleDialpadVisibility() {
if (dialpad_wrapper.isVisible()) hideDialpad() else showDialpad()
if (binding.dialpadWrapper.isVisible()) hideDialpad() else showDialpad()
}
private fun findVisibleViewsUnderDialpad(): Sequence<Pair<View, Float>> {
return ongoing_call_holder.children.filter { it.isVisible() }.map { view -> Pair(view, view.alpha) }
return binding.ongoingCallHolder.children.filter { it.isVisible() }.map { view -> Pair(view, view.alpha) }
}
private fun showDialpad() {
dialpad_wrapper.apply {
binding.dialpadWrapper.apply {
translationY = dialpadHeight
alpha = 0f
animate()
@ -507,8 +525,8 @@ class CallActivity : SimpleActivity() {
}
private fun hideDialpad() {
dialpad_wrapper.animate()
.withEndAction { dialpad_wrapper.beGone() }
binding.dialpadWrapper.animate()
.withEndAction { binding.dialpadWrapper.beGone() }
.setInterpolator(AccelerateDecelerateInterpolator())
.setDuration(200L)
.alpha(0f)
@ -525,9 +543,9 @@ class CallActivity : SimpleActivity() {
private fun toggleHold() {
val isOnHold = CallManager.toggleHold()
toggleButtonColor(call_toggle_hold, isOnHold)
call_toggle_hold.contentDescription = getString(if (isOnHold) R.string.resume_call else R.string.hold_call)
hold_status_label.beVisibleIf(isOnHold)
toggleButtonColor(binding.callToggleHold, isOnHold)
binding.callToggleHold.contentDescription = getString(if (isOnHold) R.string.resume_call else R.string.hold_call)
binding.holdStatusLabel.beVisibleIf(isOnHold)
}
private fun updateOtherPersonsInfo(avatar: Bitmap?) {
@ -535,21 +553,23 @@ class CallActivity : SimpleActivity() {
return
}
caller_name_label.text = if (callContact!!.name.isNotEmpty()) callContact!!.name else getString(R.string.unknown_caller)
if (callContact!!.number.isNotEmpty() && callContact!!.number != callContact!!.name) {
caller_number.text = callContact!!.number
binding.apply {
callerNameLabel.text = if (callContact!!.name.isNotEmpty()) callContact!!.name else getString(R.string.unknown_caller)
if (callContact!!.number.isNotEmpty() && callContact!!.number != callContact!!.name) {
callerNumber.text = callContact!!.number
if (callContact!!.numberLabel.isNotEmpty()) {
caller_number.text = "${callContact!!.number} - ${callContact!!.numberLabel}"
if (callContact!!.numberLabel.isNotEmpty()) {
callerNumber.text = "${callContact!!.number} - ${callContact!!.numberLabel}"
}
} else {
callerNumber.beGone()
}
} else {
caller_number.beGone()
}
if (avatar != null) {
caller_avatar.setImageBitmap(avatar)
} else {
caller_avatar.setImageDrawable(null)
if (avatar != null) {
callerAvatar.setImageBitmap(avatar)
} else {
callerAvatar.setImageDrawable(null)
}
}
}
@ -568,9 +588,11 @@ class CallActivity : SimpleActivity() {
if (accounts.size > 1) {
accounts.forEachIndexed { index, account ->
if (account == CallManager.getPrimaryCall()?.details?.accountHandle) {
call_sim_id.text = "${index + 1}"
call_sim_id.beVisible()
call_sim_image.beVisible()
binding.apply {
callSimId.text = "${index + 1}"
callSimId.beVisible()
callSimImage.beVisible()
}
val acceptDrawableId = when (index) {
0 -> R.drawable.ic_phone_one_vector
@ -581,7 +603,7 @@ class CallActivity : SimpleActivity() {
val rippleBg = resources.getDrawable(R.drawable.ic_call_accept, theme) as RippleDrawable
val layerDrawable = rippleBg.findDrawableByLayerId(R.id.accept_call_background_holder) as LayerDrawable
layerDrawable.setDrawableByLayerId(R.id.accept_call_icon, getDrawable(acceptDrawableId))
call_accept.setImageDrawable(rippleBg)
binding.callAccept.setImageDrawable(rippleBg)
}
}
}
@ -605,13 +627,15 @@ class CallActivity : SimpleActivity() {
else -> 0
}
if (statusTextId != 0) {
call_status_label.text = getString(statusTextId)
}
binding.apply {
if (statusTextId != 0) {
callStatusLabel.text = getString(statusTextId)
}
call_manage.beVisibleIf(call.hasCapability(Call.Details.CAPABILITY_MANAGE_CONFERENCE))
setActionButtonEnabled(call_swap, state == Call.STATE_ACTIVE)
setActionButtonEnabled(call_merge, state == Call.STATE_ACTIVE)
callManage.beVisibleIf(call.hasCapability(Call.Details.CAPABILITY_MANAGE_CONFERENCE))
setActionButtonEnabled(callSwap, state == Call.STATE_ACTIVE)
setActionButtonEnabled(callMerge, state == Call.STATE_ACTIVE)
}
}
private fun updateState() {
@ -622,8 +646,8 @@ class CallActivity : SimpleActivity() {
val state = phoneState.call.getStateCompat()
val isSingleCallActionsEnabled = (state == Call.STATE_ACTIVE || state == Call.STATE_DISCONNECTED
|| state == Call.STATE_DISCONNECTING || state == Call.STATE_HOLDING)
setActionButtonEnabled(call_toggle_hold, isSingleCallActionsEnabled)
setActionButtonEnabled(call_add, isSingleCallActionsEnabled)
setActionButtonEnabled(binding.callToggleHold, isSingleCallActionsEnabled)
setActionButtonEnabled(binding.callAdd, isSingleCallActionsEnabled)
} else if (phoneState is TwoCalls) {
updateCallState(phoneState.active)
updateCallOnHoldState(phoneState.onHold)
@ -637,13 +661,15 @@ class CallActivity : SimpleActivity() {
if (hasCallOnHold) {
getCallContact(applicationContext, call) { contact ->
runOnUiThread {
on_hold_caller_name.text = getContactNameOrNumber(contact)
binding.onHoldCallerName.text = getContactNameOrNumber(contact)
}
}
}
on_hold_status_holder.beVisibleIf(hasCallOnHold)
controls_single_call.beVisibleIf(!hasCallOnHold)
controls_two_calls.beVisibleIf(hasCallOnHold)
binding.apply {
onHoldStatusHolder.beVisibleIf(hasCallOnHold)
controlsSingleCall.beVisibleIf(!hasCallOnHold)
controlsTwoCalls.beVisibleIf(hasCallOnHold)
}
}
private fun updateCallContactInfo(call: Call?) {
@ -666,18 +692,18 @@ class CallActivity : SimpleActivity() {
private fun initOutgoingCallUI() {
enableProximitySensor()
incoming_call_holder.beGone()
ongoing_call_holder.beVisible()
binding.incomingCallHolder.beGone()
binding.ongoingCallHolder.beVisible()
}
private fun callRinging() {
incoming_call_holder.beVisible()
binding.incomingCallHolder.beVisible()
}
private fun callStarted() {
enableProximitySensor()
incoming_call_holder.beGone()
ongoing_call_holder.beVisible()
binding.incomingCallHolder.beGone()
binding.ongoingCallHolder.beVisible()
callDurationHandler.removeCallbacks(updateCallDurationTask)
callDurationHandler.post(updateCallDurationTask)
}
@ -708,13 +734,13 @@ class CallActivity : SimpleActivity() {
isCallEnded = true
if (callDuration > 0) {
runOnUiThread {
call_status_label.text = "${callDuration.getFormattedDuration()} (${getString(R.string.call_ended)})"
binding.callStatusLabel.text = "${callDuration.getFormattedDuration()} (${getString(R.string.call_ended)})"
Handler().postDelayed({
finishAndRemoveTask()
}, 3000)
}
} else {
call_status_label.text = getString(R.string.call_ended)
binding.callStatusLabel.text = getString(R.string.call_ended)
finish()
}
}
@ -739,7 +765,7 @@ class CallActivity : SimpleActivity() {
override fun run() {
callDuration = CallManager.getPrimaryCall().getCallDuration()
if (!isCallEnded) {
call_status_label.text = callDuration.getFormattedDuration()
binding.callStatusLabel.text = callDuration.getFormattedDuration()
callDurationHandler.postDelayed(this, 1000)
}
}

View File

@ -1,25 +1,28 @@
package com.simplemobiletools.dialer.activities
import android.os.Bundle
import com.simplemobiletools.commons.extensions.viewBinding
import com.simplemobiletools.commons.helpers.NavigationIcon
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.adapters.ConferenceCallsAdapter
import com.simplemobiletools.dialer.databinding.ActivityConferenceBinding
import com.simplemobiletools.dialer.helpers.CallManager
import kotlinx.android.synthetic.main.activity_conference.*
class ConferenceActivity : SimpleActivity() {
private val binding by viewBinding(ActivityConferenceBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_conference)
updateMaterialActivityViews(conference_coordinator, conference_list, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(conference_list, conference_toolbar)
conference_list.adapter = ConferenceCallsAdapter(this, conference_list, ArrayList(CallManager.getConferenceCalls())) {}
setContentView(binding.root)
binding.apply {
updateMaterialActivityViews(conferenceCoordinator, conferenceList, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(conferenceList, conferenceToolbar)
conferenceList.adapter = ConferenceCallsAdapter(this@ConferenceActivity, conferenceList, ArrayList(CallManager.getConferenceCalls())) {}
}
}
override fun onResume() {
super.onResume()
setupToolbar(conference_toolbar, NavigationIcon.Arrow)
setupToolbar(binding.conferenceToolbar, NavigationIcon.Arrow)
}
}

View File

@ -20,22 +20,23 @@ import android.view.ViewConfiguration
import androidx.core.content.res.ResourcesCompat
import androidx.core.view.isVisible
import com.reddit.indicatorfastscroll.FastScrollItemIndicator
import com.simplemobiletools.commons.dialogs.CallConfirmationDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.contacts.Contact
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.adapters.ContactsAdapter
import com.simplemobiletools.dialer.databinding.ActivityDialpadBinding
import com.simplemobiletools.dialer.extensions.*
import com.simplemobiletools.dialer.helpers.DIALPAD_TONE_LENGTH_MS
import com.simplemobiletools.dialer.helpers.ToneGeneratorHelper
import com.simplemobiletools.dialer.models.SpeedDial
import kotlinx.android.synthetic.main.activity_dialpad.*
import kotlinx.android.synthetic.main.activity_dialpad.dialpad_holder
import kotlinx.android.synthetic.main.dialpad.*
import java.util.*
import kotlin.math.roundToInt
class DialpadActivity : SimpleActivity() {
private val binding by viewBinding(ActivityDialpadBinding::inflate)
private var allContacts = ArrayList<Contact>()
private var speedDialValues = ArrayList<SpeedDial>()
private val russianCharsMap = HashMap<Char, Int>()
@ -48,48 +49,53 @@ class DialpadActivity : SimpleActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_dialpad)
setContentView(binding.root)
hasRussianLocale = Locale.getDefault().language == "ru"
updateMaterialActivityViews(dialpad_coordinator, dialpad_holder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(dialpad_list, dialpad_toolbar)
binding.apply {
updateMaterialActivityViews(dialpadCoordinator, dialpadHolder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(dialpadList, dialpadToolbar)
}
updateNavigationBarColor(getProperBackgroundColor())
if (checkAppSideloading()) {
return
}
if (config.hideDialpadNumbers) {
dialpad_1_holder.isVisible = false
dialpad_2_holder.isVisible = false
dialpad_3_holder.isVisible = false
dialpad_4_holder.isVisible = false
dialpad_5_holder.isVisible = false
dialpad_6_holder.isVisible = false
dialpad_7_holder.isVisible = false
dialpad_8_holder.isVisible = false
dialpad_9_holder.isVisible = false
dialpad_plus_holder.isVisible = true
dialpad_0_holder.visibility = View.INVISIBLE
}
binding.dialpadWrapper.apply {
if (config.hideDialpadNumbers) {
dialpad1Holder.isVisible = false
dialpad2Holder.isVisible = false
dialpad3Holder.isVisible = false
dialpad4Holder.isVisible = false
dialpad5Holder.isVisible = false
dialpad6Holder.isVisible = false
dialpad7Holder.isVisible = false
dialpad8Holder.isVisible = false
dialpad9Holder.isVisible = false
dialpadPlusHolder.isVisible = true
dialpad0Holder.visibility = View.INVISIBLE
}
arrayOf(
dialpad_0_holder,
dialpad_1_holder,
dialpad_2_holder,
dialpad_3_holder,
dialpad_4_holder,
dialpad_5_holder,
dialpad_6_holder,
dialpad_7_holder,
dialpad_8_holder,
dialpad_9_holder,
dialpad_plus_holder,
dialpad_asterisk_holder,
dialpad_hashtag_holder
).forEach {
it.background = ResourcesCompat.getDrawable(resources, R.drawable.pill_background, theme)
it.background?.alpha = LOWER_ALPHA_INT
arrayOf(
dialpad0Holder,
dialpad1Holder,
dialpad2Holder,
dialpad3Holder,
dialpad4Holder,
dialpad5Holder,
dialpad6Holder,
dialpad7Holder,
dialpad8Holder,
dialpad9Holder,
dialpadPlusHolder,
dialpadAsteriskHolder,
dialpadHashtagHolder
).forEach {
it.background = ResourcesCompat.getDrawable(resources, R.drawable.pill_background, theme)
it.background?.alpha = LOWER_ALPHA_INT
}
}
setupOptionsMenu()
@ -98,57 +104,65 @@ class DialpadActivity : SimpleActivity() {
toneGeneratorHelper = ToneGeneratorHelper(this, DIALPAD_TONE_LENGTH_MS)
if (hasRussianLocale) {
initRussianChars()
dialpad_2_letters.append("\nАБВГ")
dialpad_3_letters.append("\nДЕЁЖЗ")
dialpad_4_letters.append("\nИЙКЛ")
dialpad_5_letters.append("\nМНОП")
dialpad_6_letters.append("\nРСТУ")
dialpad_7_letters.append("\nФХЦЧ")
dialpad_8_letters.append("\nШЩЪЫ")
dialpad_9_letters.append("\nЬЭЮЯ")
binding.dialpadWrapper.apply {
if (hasRussianLocale) {
initRussianChars()
dialpad2Letters.append("\nАБВГ")
dialpad3Letters.append("\nДЕЁЖЗ")
dialpad4Letters.append("\nИЙКЛ")
dialpad5Letters.append("\nМНОП")
dialpad6Letters.append("\nРСТУ")
dialpad7Letters.append("\nФХЦЧ")
dialpad8Letters.append("\nШЩЪЫ")
dialpad9Letters.append("\nЬЭЮЯ")
val fontSize = resources.getDimension(R.dimen.small_text_size)
arrayOf(
dialpad_2_letters, dialpad_3_letters, dialpad_4_letters, dialpad_5_letters, dialpad_6_letters, dialpad_7_letters, dialpad_8_letters,
dialpad_9_letters
).forEach {
it.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
val fontSize = resources.getDimension(R.dimen.small_text_size)
arrayOf(
dialpad2Letters, dialpad3Letters, dialpad4Letters, dialpad5Letters, dialpad6Letters, dialpad7Letters, dialpad8Letters,
dialpad9Letters
).forEach {
it.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
}
}
setupCharClick(dialpad1Holder, '1')
setupCharClick(dialpad2Holder, '2')
setupCharClick(dialpad3Holder, '3')
setupCharClick(dialpad4Holder, '4')
setupCharClick(dialpad5Holder, '5')
setupCharClick(dialpad6Holder, '6')
setupCharClick(dialpad7Holder, '7')
setupCharClick(dialpad8Holder, '8')
setupCharClick(dialpad9Holder, '9')
setupCharClick(dialpad0Holder, '0')
setupCharClick(dialpadPlusHolder, '+', longClickable = false)
setupCharClick(dialpadAsteriskHolder, '*', longClickable = false)
setupCharClick(dialpadHashtagHolder, '#', longClickable = false)
}
setupCharClick(dialpad_1_holder, '1')
setupCharClick(dialpad_2_holder, '2')
setupCharClick(dialpad_3_holder, '3')
setupCharClick(dialpad_4_holder, '4')
setupCharClick(dialpad_5_holder, '5')
setupCharClick(dialpad_6_holder, '6')
setupCharClick(dialpad_7_holder, '7')
setupCharClick(dialpad_8_holder, '8')
setupCharClick(dialpad_9_holder, '9')
setupCharClick(dialpad_0_holder, '0')
setupCharClick(dialpad_plus_holder, '+', longClickable = false)
setupCharClick(dialpad_asterisk_holder, '*', longClickable = false)
setupCharClick(dialpad_hashtag_holder, '#', longClickable = false)
binding.apply {
dialpadClearChar.setOnClickListener { clearChar(it) }
dialpadClearChar.setOnLongClickListener { clearInput(); true }
dialpadCallButton.setOnClickListener { initCall(dialpadInput.value, 0) }
dialpadInput.onTextChangeListener { dialpadValueChanged(it) }
dialpadInput.requestFocus()
dialpadInput.disableKeyboard()
}
dialpad_clear_char.setOnClickListener { clearChar(it) }
dialpad_clear_char.setOnLongClickListener { clearInput(); true }
dialpad_call_button.setOnClickListener { initCall(dialpad_input.value, 0) }
dialpad_input.onTextChangeListener { dialpadValueChanged(it) }
dialpad_input.requestFocus()
ContactsHelper(this).getContacts{ gotContacts(it) }
dialpad_input.disableKeyboard()
ContactsHelper(this).getContacts(showOnlyContactsWithNumbers = true) { allContacts ->
gotContacts(allContacts)
}
val properPrimaryColor = getProperPrimaryColor()
val callIconId = if (areMultipleSIMsAvailable()) {
val callIcon = resources.getColoredDrawableWithColor(R.drawable.ic_phone_two_vector, properPrimaryColor.getContrastColor())
dialpad_call_two_button.setImageDrawable(callIcon)
dialpad_call_two_button.background.applyColorFilter(properPrimaryColor)
dialpad_call_two_button.beVisible()
dialpad_call_two_button.setOnClickListener {
initCall(dialpad_input.value, 1)
binding.apply {
dialpadCallTwoButton.setImageDrawable(callIcon)
dialpadCallTwoButton.background.applyColorFilter(properPrimaryColor)
dialpadCallTwoButton.beVisible()
dialpadCallTwoButton.setOnClickListener {
initCall(dialpadInput.value, 1)
}
}
R.drawable.ic_phone_one_vector
@ -156,27 +170,29 @@ class DialpadActivity : SimpleActivity() {
R.drawable.ic_phone_vector
}
val callIcon = resources.getColoredDrawableWithColor(callIconId, properPrimaryColor.getContrastColor())
dialpad_call_button.setImageDrawable(callIcon)
dialpad_call_button.background.applyColorFilter(properPrimaryColor)
binding.apply {
val callIcon = resources.getColoredDrawableWithColor(callIconId, properPrimaryColor.getContrastColor())
dialpadCallButton.setImageDrawable(callIcon)
dialpadCallButton.background.applyColorFilter(properPrimaryColor)
letter_fastscroller.textColor = getProperTextColor().getColorStateList()
letter_fastscroller.pressedTextColor = properPrimaryColor
letter_fastscroller_thumb.setupWithFastScroller(letter_fastscroller)
letter_fastscroller_thumb.textColor = properPrimaryColor.getContrastColor()
letter_fastscroller_thumb.thumbColor = properPrimaryColor.getColorStateList()
letterFastscroller.textColor = getProperTextColor().getColorStateList()
letterFastscroller.pressedTextColor = properPrimaryColor
letterFastscrollerThumb.setupWithFastScroller(letterFastscroller)
letterFastscrollerThumb.textColor = properPrimaryColor.getContrastColor()
letterFastscrollerThumb.thumbColor = properPrimaryColor.getColorStateList()
}
}
override fun onResume() {
super.onResume()
updateTextColors(dialpad_holder)
dialpad_clear_char.applyColorFilter(getProperTextColor())
updateTextColors(binding.dialpadHolder)
binding.dialpadClearChar.applyColorFilter(getProperTextColor())
updateNavigationBarColor(getProperBackgroundColor())
setupToolbar(dialpad_toolbar, NavigationIcon.Arrow)
setupToolbar(binding.dialpadToolbar, NavigationIcon.Arrow)
}
private fun setupOptionsMenu() {
dialpad_toolbar.setOnMenuItemClickListener { menuItem ->
binding.dialpadToolbar.setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) {
R.id.add_number_to_contact -> addNumberToContact()
else -> return@setOnMenuItemClickListener false
@ -188,8 +204,8 @@ class DialpadActivity : SimpleActivity() {
private fun checkDialIntent(): Boolean {
return if ((intent.action == Intent.ACTION_DIAL || intent.action == Intent.ACTION_VIEW) && intent.data != null && intent.dataString?.contains("tel:") == true) {
val number = Uri.decode(intent.dataString).substringAfter("tel:")
dialpad_input.setText(number)
dialpad_input.setSelection(number.length)
binding.dialpadInput.setText(number)
binding.dialpadInput.setSelection(number.length)
true
} else {
false
@ -200,23 +216,23 @@ class DialpadActivity : SimpleActivity() {
Intent().apply {
action = Intent.ACTION_INSERT_OR_EDIT
type = "vnd.android.cursor.item/contact"
putExtra(KEY_PHONE, dialpad_input.value)
putExtra(KEY_PHONE, binding.dialpadInput.value)
launchActivityIntent(this)
}
}
private fun dialpadPressed(char: Char, view: View?) {
dialpad_input.addCharacter(char)
binding.dialpadInput.addCharacter(char)
maybePerformDialpadHapticFeedback(view)
}
private fun clearChar(view: View) {
dialpad_input.dispatchKeyEvent(dialpad_input.getKeyEvent(KeyEvent.KEYCODE_DEL))
binding.dialpadInput.dispatchKeyEvent(binding.dialpadInput.getKeyEvent(KeyEvent.KEYCODE_DEL))
maybePerformDialpadHapticFeedback(view)
}
private fun clearInput() {
dialpad_input.setText("")
binding.dialpadInput.setText("")
}
private fun gotContacts(newContacts: ArrayList<Contact>) {
@ -229,7 +245,7 @@ class DialpadActivity : SimpleActivity() {
}
runOnUiThread {
if (!checkDialIntent() && dialpad_input.value.isEmpty()) {
if (!checkDialIntent() && binding.dialpadInput.value.isEmpty()) {
dialpadValueChanged("")
}
}
@ -253,14 +269,14 @@ class DialpadActivity : SimpleActivity() {
return
}
(dialpad_list.adapter as? ContactsAdapter)?.finishActMode()
(binding.dialpadList.adapter as? ContactsAdapter)?.finishActMode()
val filtered = allContacts.filter {
var convertedName = PhoneNumberUtils.convertKeypadLettersToDigits(it.name.normalizeString())
if (hasRussianLocale) {
var currConvertedName = ""
convertedName.toLowerCase().forEach { char ->
convertedName.lowercase(Locale.getDefault()).forEach { char ->
val convertedChar = russianCharsMap.getOrElse(char) { char }
currConvertedName += convertedChar
}
@ -272,45 +288,69 @@ class DialpadActivity : SimpleActivity() {
!it.doesContainPhoneNumber(text)
}).toMutableList() as ArrayList<Contact>
letter_fastscroller.setupWithRecyclerView(dialpad_list, { position ->
binding.letterFastscroller.setupWithRecyclerView(binding.dialpadList, { position ->
try {
val name = filtered[position].getNameToDisplay()
val character = if (name.isNotEmpty()) name.substring(0, 1) else ""
FastScrollItemIndicator.Text(character.toUpperCase(Locale.getDefault()))
FastScrollItemIndicator.Text(character.uppercase(Locale.getDefault()))
} catch (e: Exception) {
FastScrollItemIndicator.Text("")
}
})
ContactsAdapter(this, filtered, dialpad_list, null, text) {
startCallIntent((it as Contact).phoneNumbers.first().normalizedNumber)
ContactsAdapter(
activity = this,
contacts = filtered,
recyclerView = binding.dialpadList,
highlightText = text
) {
val contact = it as Contact
if (config.showCallConfirmation) {
CallConfirmationDialog(this@DialpadActivity, contact.getNameToDisplay()) {
startCallIntent(contact.getPrimaryNumber() ?: return@CallConfirmationDialog)
}
} else {
startCallIntent(contact.getPrimaryNumber() ?: return@ContactsAdapter)
}
}.apply {
dialpad_list.adapter = this
binding.dialpadList.adapter = this
}
dialpad_placeholder.beVisibleIf(filtered.isEmpty())
dialpad_list.beVisibleIf(filtered.isNotEmpty())
binding.dialpadPlaceholder.beVisibleIf(filtered.isEmpty())
binding.dialpadList.beVisibleIf(filtered.isNotEmpty())
}
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
super.onActivityResult(requestCode, resultCode, resultData)
if (requestCode == REQUEST_CODE_SET_DEFAULT_DIALER && isDefaultDialer()) {
dialpadValueChanged(dialpad_input.value)
dialpadValueChanged(binding.dialpadInput.value)
}
}
private fun initCall(number: String = dialpad_input.value, handleIndex: Int) {
private fun initCall(number: String = binding.dialpadInput.value, handleIndex: Int) {
if (number.isNotEmpty()) {
if (handleIndex != -1 && areMultipleSIMsAvailable()) {
callContactWithSim(number, handleIndex == 0)
if (config.showCallConfirmation) {
CallConfirmationDialog(this, number) {
callContactWithSim(number, handleIndex == 0)
}
} else {
callContactWithSim(number, handleIndex == 0)
}
} else {
startCallIntent(number)
if (config.showCallConfirmation) {
CallConfirmationDialog(this, number) {
startCallIntent(number)
}
} else {
startCallIntent(number)
}
}
}
}
private fun speedDial(id: Int): Boolean {
if (dialpad_input.value.length == 1) {
if (binding.dialpadInput.value.length == 1) {
val speedDial = speedDialValues.firstOrNull { it.id == id }
if (speedDial?.isValid() == true) {
initCall(speedDial.number, -1)
@ -384,12 +424,14 @@ class DialpadActivity : SimpleActivity() {
}, longPressTimeout)
}
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
stopDialpadTone(char)
if (longClickable) {
longPressHandler.removeCallbacksAndMessages(null)
}
}
MotionEvent.ACTION_MOVE -> {
val viewContainsTouchEvent = if (event.rawX.isNaN() || event.rawY.isNaN()) {
false

View File

@ -16,43 +16,47 @@ import android.widget.TextView
import android.widget.Toast
import androidx.viewpager.widget.ViewPager
import com.google.android.material.snackbar.Snackbar
import com.simplemobiletools.commons.dialogs.ChangeViewTypeDialog
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.dialogs.PermissionRequiredDialog
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.FAQItem
import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.commons.models.contacts.Contact
import com.simplemobiletools.dialer.BuildConfig
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.adapters.ViewPagerAdapter
import com.simplemobiletools.dialer.databinding.ActivityMainBinding
import com.simplemobiletools.dialer.dialogs.ChangeSortingDialog
import com.simplemobiletools.dialer.dialogs.FilterContactSourcesDialog
import com.simplemobiletools.dialer.extensions.config
import com.simplemobiletools.dialer.extensions.launchCreateNewContactIntent
import com.simplemobiletools.dialer.fragments.ContactsFragment
import com.simplemobiletools.dialer.fragments.FavoritesFragment
import com.simplemobiletools.dialer.fragments.MyViewPagerFragment
import com.simplemobiletools.dialer.helpers.OPEN_DIAL_PAD_AT_LAUNCH
import com.simplemobiletools.dialer.helpers.RecentsHelper
import com.simplemobiletools.dialer.helpers.tabsList
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.fragment_contacts.*
import kotlinx.android.synthetic.main.fragment_favorites.*
import kotlinx.android.synthetic.main.fragment_recents.*
import com.simplemobiletools.dialer.fragments.RecentsFragment
import com.simplemobiletools.dialer.helpers.*
import me.grantland.widget.AutofitHelper
class MainActivity : SimpleActivity() {
private val binding by viewBinding(ActivityMainBinding::inflate)
private var launchedDialer = false
private var storedShowTabs = 0
private var storedFontSize = 0
private var storedStartNameWithSurname = false
var cachedContacts = ArrayList<Contact>()
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setContentView(binding.root)
appLaunched(BuildConfig.APPLICATION_ID)
setupOptionsMenu()
refreshMenuItems()
updateMaterialActivityViews(main_coordinator, main_holder, useTransparentNavigation = false, useTopSearchMenu = true)
updateMaterialActivityViews(binding.mainCoordinator, binding.mainHolder, useTransparentNavigation = false, useTopSearchMenu = true)
launchedDialer = savedInstanceState?.getBoolean(OPEN_DIAL_PAD_AT_LAUNCH) ?: false
@ -60,7 +64,7 @@ class MainActivity : SimpleActivity() {
checkContactPermissions()
if (!config.wasOverlaySnackbarConfirmed && !Settings.canDrawOverlays(this)) {
val snackbar = Snackbar.make(main_holder, R.string.allow_displaying_over_other_apps, Snackbar.LENGTH_INDEFINITE).setAction(R.string.ok) {
val snackbar = Snackbar.make(binding.mainHolder, R.string.allow_displaying_over_other_apps, Snackbar.LENGTH_INDEFINITE).setAction(R.string.ok) {
config.wasOverlaySnackbarConfirmed = true
startActivity(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION))
}
@ -73,14 +77,14 @@ class MainActivity : SimpleActivity() {
handleNotificationPermission { granted ->
if (!granted) {
toast(R.string.no_post_notifications_permissions)
PermissionRequiredDialog(this, R.string.allow_notifications_incoming_calls, { openNotificationSettings() })
}
}
} else {
launchSetDefaultDialerIntent()
}
if (isQPlus() && config.blockUnknownNumbers) {
if (isQPlus() && (config.blockUnknownNumbers || config.blockHiddenNumbers)) {
setDefaultCallerIdApp()
}
@ -99,9 +103,9 @@ class MainActivity : SimpleActivity() {
updateMenuColors()
val properPrimaryColor = getProperPrimaryColor()
val dialpadIcon = resources.getColoredDrawableWithColor(R.drawable.ic_dialpad_vector, properPrimaryColor.getContrastColor())
main_dialpad_button.setImageDrawable(dialpadIcon)
binding.mainDialpadButton.setImageDrawable(dialpadIcon)
updateTextColors(main_holder)
updateTextColors(binding.mainHolder)
setupTabColors()
getAllFragments().forEach {
@ -110,18 +114,25 @@ class MainActivity : SimpleActivity() {
val configStartNameWithSurname = config.startNameWithSurname
if (storedStartNameWithSurname != configStartNameWithSurname) {
contacts_fragment?.startNameWithSurnameChanged(configStartNameWithSurname)
favorites_fragment?.startNameWithSurnameChanged(configStartNameWithSurname)
getContactsFragment()?.startNameWithSurnameChanged(configStartNameWithSurname)
getFavoritesFragment()?.startNameWithSurnameChanged(configStartNameWithSurname)
storedStartNameWithSurname = config.startNameWithSurname
}
if (!main_menu.isSearchOpen) {
if (!binding.mainMenu.isSearchOpen) {
refreshItems(true)
}
val configFontSize = config.fontSize
if (storedFontSize != configFontSize) {
getAllFragments().forEach {
it?.fontSizeChanged()
}
}
checkShortcuts()
Handler().postDelayed({
recents_fragment?.refreshItems()
getRecentsFragment()?.refreshItems()
}, 2000)
}
@ -129,7 +140,7 @@ class MainActivity : SimpleActivity() {
super.onPause()
storedShowTabs = config.showTabs
storedStartNameWithSurname = config.startNameWithSurname
config.lastUsedViewPagerPage = view_pager.currentItem
config.lastUsedViewPagerPage = binding.viewPager.currentItem
}
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
@ -140,6 +151,7 @@ class MainActivity : SimpleActivity() {
} else if (requestCode == REQUEST_CODE_SET_DEFAULT_CALLER_ID && resultCode != Activity.RESULT_OK) {
toast(R.string.must_make_default_caller_id_app, length = Toast.LENGTH_LONG)
baseConfig.blockUnknownNumbers = false
baseConfig.blockHiddenNumbers = false
}
}
@ -154,8 +166,8 @@ class MainActivity : SimpleActivity() {
}
override fun onBackPressed() {
if (main_menu.isSearchOpen) {
main_menu.closeSearch()
if (binding.mainMenu.isSearchOpen) {
binding.mainMenu.closeSearch()
} else {
super.onBackPressed()
}
@ -163,47 +175,76 @@ class MainActivity : SimpleActivity() {
private fun refreshMenuItems() {
val currentFragment = getCurrentFragment()
main_menu.getToolbar().menu.apply {
findItem(R.id.clear_call_history).isVisible = currentFragment == recents_fragment
findItem(R.id.sort).isVisible = currentFragment != recents_fragment
findItem(R.id.create_new_contact).isVisible = currentFragment == contacts_fragment
binding.mainMenu.getToolbar().menu.apply {
findItem(R.id.clear_call_history).isVisible = currentFragment == getRecentsFragment()
findItem(R.id.sort).isVisible = currentFragment != getRecentsFragment()
findItem(R.id.create_new_contact).isVisible = currentFragment == getContactsFragment()
findItem(R.id.change_view_type).isVisible = currentFragment == getFavoritesFragment()
findItem(R.id.column_count).isVisible = currentFragment == getFavoritesFragment() && config.viewType == VIEW_TYPE_GRID
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(R.bool.hide_google_relations)
}
}
private fun setupOptionsMenu() {
main_menu.getToolbar().inflateMenu(R.menu.menu)
main_menu.toggleHideOnScroll(false)
main_menu.setupMenu()
binding.mainMenu.apply {
getToolbar().inflateMenu(R.menu.menu)
toggleHideOnScroll(false)
setupMenu()
main_menu.onSearchClosedListener = {
getAllFragments().forEach {
it?.onSearchQueryChanged("")
onSearchClosedListener = {
getAllFragments().forEach {
it?.onSearchQueryChanged("")
}
}
onSearchTextChangedListener = { text ->
getCurrentFragment()?.onSearchQueryChanged(text)
}
getToolbar().setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) {
R.id.clear_call_history -> clearCallHistory()
R.id.create_new_contact -> launchCreateNewContactIntent()
R.id.sort -> showSortingDialog(showCustomSorting = getCurrentFragment() is FavoritesFragment)
R.id.filter -> showFilterDialog()
R.id.more_apps_from_us -> launchMoreAppsFromUsIntent()
R.id.settings -> launchSettings()
R.id.change_view_type -> changeViewType()
R.id.column_count -> changeColumnCount()
R.id.about -> launchAbout()
else -> return@setOnMenuItemClickListener false
}
return@setOnMenuItemClickListener true
}
}
}
main_menu.onSearchTextChangedListener = { text ->
getCurrentFragment()?.onSearchQueryChanged(text)
private fun changeColumnCount() {
val items = ArrayList<RadioItem>()
for (i in 1..CONTACTS_GRID_MAX_COLUMNS_COUNT) {
items.add(RadioItem(i, resources.getQuantityString(R.plurals.column_counts, i, i)))
}
main_menu.getToolbar().setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) {
R.id.clear_call_history -> clearCallHistory()
R.id.create_new_contact -> launchCreateNewContactIntent()
R.id.sort -> showSortingDialog(showCustomSorting = getCurrentFragment() is FavoritesFragment)
R.id.filter -> showFilterDialog()
R.id.more_apps_from_us -> launchMoreAppsFromUsIntent()
R.id.settings -> launchSettings()
R.id.about -> launchAbout()
else -> return@setOnMenuItemClickListener false
val currentColumnCount = config.contactsGridColumnCount
RadioGroupDialog(this, ArrayList(items), currentColumnCount) {
val newColumnCount = it as Int
if (currentColumnCount != newColumnCount) {
config.contactsGridColumnCount = newColumnCount
getFavoritesFragment()?.columnCountChanged()
}
return@setOnMenuItemClickListener true
}
}
private fun changeViewType() {
ChangeViewTypeDialog(this) {
refreshMenuItems()
getFavoritesFragment()?.refreshItems()
}
}
private fun updateMenuColors() {
updateStatusbarColor(getProperBackgroundColor())
main_menu.updateColors()
binding.mainMenu.updateColors()
}
private fun checkContactPermissions() {
@ -213,11 +254,11 @@ class MainActivity : SimpleActivity() {
}
private fun clearCallHistory() {
val confirmationText = "${getString(R.string.remove_confirmation)}\n\n${getString(R.string.cannot_be_undone)}"
val confirmationText = "${getString(R.string.clear_history_confirmation)}\n\n${getString(R.string.cannot_be_undone)}"
ConfirmationDialog(this, confirmationText) {
RecentsHelper(this).removeAllRecentCalls(this) {
runOnUiThread {
recents_fragment?.refreshItems()
getRecentsFragment()?.refreshItems()
}
}
}
@ -255,24 +296,24 @@ class MainActivity : SimpleActivity() {
}
private fun setupTabColors() {
val activeView = main_tabs_holder.getTabAt(view_pager.currentItem)?.customView
updateBottomTabItemColors(activeView, true, getSelectedTabDrawableIds()[view_pager.currentItem])
val activeView = binding.mainTabsHolder.getTabAt(binding.viewPager.currentItem)?.customView
updateBottomTabItemColors(activeView, true, getSelectedTabDrawableIds()[binding.viewPager.currentItem])
getInactiveTabIndexes(view_pager.currentItem).forEach { index ->
val inactiveView = main_tabs_holder.getTabAt(index)?.customView
getInactiveTabIndexes(binding.viewPager.currentItem).forEach { index ->
val inactiveView = binding.mainTabsHolder.getTabAt(index)?.customView
updateBottomTabItemColors(inactiveView, false, getDeselectedTabDrawableIds()[index])
}
val bottomBarColor = getBottomNavigationBackgroundColor()
main_tabs_holder.setBackgroundColor(bottomBarColor)
binding.mainTabsHolder.setBackgroundColor(bottomBarColor)
updateNavigationBarColor(bottomBarColor)
}
private fun getInactiveTabIndexes(activeIndex: Int) = (0 until main_tabs_holder.tabCount).filter { it != activeIndex }
private fun getInactiveTabIndexes(activeIndex: Int) = (0 until binding.mainTabsHolder.tabCount).filter { it != activeIndex }
private fun getSelectedTabDrawableIds(): ArrayList<Int> {
private fun getSelectedTabDrawableIds(): List<Int> {
val showTabs = config.showTabs
val icons = ArrayList<Int>()
val icons = mutableListOf<Int>()
if (showTabs and TAB_CONTACTS != 0) {
icons.add(R.drawable.ic_person_vector)
@ -309,14 +350,14 @@ class MainActivity : SimpleActivity() {
}
private fun initFragments() {
view_pager.offscreenPageLimit = 2
view_pager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
binding.viewPager.offscreenPageLimit = 2
binding.viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
override fun onPageSelected(position: Int) {
main_tabs_holder.getTabAt(position)?.select()
binding.mainTabsHolder.getTabAt(position)?.select()
getAllFragments().forEach {
it?.finishActMode()
}
@ -325,29 +366,29 @@ class MainActivity : SimpleActivity() {
})
// selecting the proper tab sometimes glitches, add an extra selector to make sure we have it right
main_tabs_holder.onGlobalLayout {
binding.mainTabsHolder.onGlobalLayout {
Handler().postDelayed({
var wantedTab = getDefaultTab()
// open the Recents tab if we got here by clicking a missed call notification
if (intent.action == Intent.ACTION_VIEW && config.showTabs and TAB_CALL_HISTORY > 0) {
wantedTab = main_tabs_holder.tabCount - 1
wantedTab = binding.mainTabsHolder.tabCount - 1
ensureBackgroundThread {
clearMissedCalls()
}
}
main_tabs_holder.getTabAt(wantedTab)?.select()
binding.mainTabsHolder.getTabAt(wantedTab)?.select()
refreshMenuItems()
}, 100L)
}
main_dialpad_button.setOnClickListener {
binding.mainDialpadButton.setOnClickListener {
launchDialpad()
}
view_pager.onGlobalLayout {
binding.viewPager.onGlobalLayout {
refreshMenuItems()
}
@ -358,31 +399,31 @@ class MainActivity : SimpleActivity() {
}
private fun setupTabs() {
view_pager.adapter = null
main_tabs_holder.removeAllTabs()
binding.viewPager.adapter = null
binding.mainTabsHolder.removeAllTabs()
tabsList.forEachIndexed { index, value ->
if (config.showTabs and value != 0) {
main_tabs_holder.newTab().setCustomView(R.layout.bottom_tablayout_item).apply {
binding.mainTabsHolder.newTab().setCustomView(R.layout.bottom_tablayout_item).apply {
customView?.findViewById<ImageView>(R.id.tab_item_icon)?.setImageDrawable(getTabIcon(index))
customView?.findViewById<TextView>(R.id.tab_item_label)?.text = getTabLabel(index)
AutofitHelper.create(customView?.findViewById(R.id.tab_item_label))
main_tabs_holder.addTab(this)
binding.mainTabsHolder.addTab(this)
}
}
}
main_tabs_holder.onTabSelectionChanged(
binding.mainTabsHolder.onTabSelectionChanged(
tabUnselectedAction = {
updateBottomTabItemColors(it.customView, false, getDeselectedTabDrawableIds()[it.position])
},
tabSelectedAction = {
main_menu.closeSearch()
view_pager.currentItem = it.position
binding.mainMenu.closeSearch()
binding.viewPager.currentItem = it.position
updateBottomTabItemColors(it.customView, true, getSelectedTabDrawableIds()[it.position])
}
)
main_tabs_holder.beGoneIf(main_tabs_holder.tabCount == 1)
binding.mainTabsHolder.beGoneIf(binding.mainTabsHolder.tabCount == 1)
storedShowTabs = config.showTabs
storedStartNameWithSurname = config.startNameWithSurname
}
@ -412,14 +453,16 @@ class MainActivity : SimpleActivity() {
return
}
if (view_pager.adapter == null) {
view_pager.adapter = ViewPagerAdapter(this)
view_pager.currentItem = if (openLastTab) config.lastUsedViewPagerPage else getDefaultTab()
view_pager.onGlobalLayout {
binding.apply {
if (viewPager.adapter == null) {
viewPager.adapter = ViewPagerAdapter(this@MainActivity)
viewPager.currentItem = if (openLastTab) config.lastUsedViewPagerPage else getDefaultTab()
viewPager.onGlobalLayout {
refreshFragments()
}
} else {
refreshFragments()
}
} else {
refreshFragments()
}
}
@ -430,36 +473,42 @@ class MainActivity : SimpleActivity() {
}
fun refreshFragments() {
contacts_fragment?.refreshItems()
favorites_fragment?.refreshItems()
recents_fragment?.refreshItems()
getContactsFragment()?.refreshItems()
getFavoritesFragment()?.refreshItems()
getRecentsFragment()?.refreshItems()
}
private fun getAllFragments(): ArrayList<MyViewPagerFragment?> {
private fun getAllFragments(): ArrayList<MyViewPagerFragment<*>?> {
val showTabs = config.showTabs
val fragments = arrayListOf<MyViewPagerFragment?>()
val fragments = arrayListOf<MyViewPagerFragment<*>?>()
if (showTabs and TAB_CONTACTS > 0) {
fragments.add(contacts_fragment)
fragments.add(getContactsFragment())
}
if (showTabs and TAB_FAVORITES > 0) {
fragments.add(favorites_fragment)
fragments.add(getFavoritesFragment())
}
if (showTabs and TAB_CALL_HISTORY > 0) {
fragments.add(recents_fragment)
fragments.add(getRecentsFragment())
}
return fragments
}
private fun getCurrentFragment(): MyViewPagerFragment? = getAllFragments().getOrNull(view_pager.currentItem)
private fun getCurrentFragment(): MyViewPagerFragment<*>? = getAllFragments().getOrNull(binding.viewPager.currentItem)
private fun getContactsFragment(): ContactsFragment? = findViewById(R.id.contacts_fragment)
private fun getFavoritesFragment(): FavoritesFragment? = findViewById(R.id.favorites_fragment)
private fun getRecentsFragment(): RecentsFragment? = findViewById(R.id.recents_fragment)
private fun getDefaultTab(): Int {
val showTabsMask = config.showTabs
return when (config.defaultTab) {
TAB_LAST_USED -> if (config.lastUsedViewPagerPage < main_tabs_holder.tabCount) config.lastUsedViewPagerPage else 0
TAB_LAST_USED -> if (config.lastUsedViewPagerPage < binding.mainTabsHolder.tabCount) config.lastUsedViewPagerPage else 0
TAB_CONTACTS -> 0
TAB_FAVORITES -> if (showTabsMask and TAB_CONTACTS > 0) 1 else 0
else -> {
@ -518,40 +567,42 @@ class MainActivity : SimpleActivity() {
private fun showSortingDialog(showCustomSorting: Boolean) {
ChangeSortingDialog(this, showCustomSorting) {
favorites_fragment?.refreshItems {
if (main_menu.isSearchOpen) {
getCurrentFragment()?.onSearchQueryChanged(main_menu.getCurrentQuery())
getFavoritesFragment()?.refreshItems {
if (binding.mainMenu.isSearchOpen) {
getCurrentFragment()?.onSearchQueryChanged(binding.mainMenu.getCurrentQuery())
}
}
contacts_fragment?.refreshItems {
if (main_menu.isSearchOpen) {
getCurrentFragment()?.onSearchQueryChanged(main_menu.getCurrentQuery())
getContactsFragment()?.refreshItems {
if (binding.mainMenu.isSearchOpen) {
getCurrentFragment()?.onSearchQueryChanged(binding.mainMenu.getCurrentQuery())
}
}
}
}
private fun showFilterDialog() {
FilterContactSourcesDialog(this) {
favorites_fragment?.refreshItems {
if (main_menu.isSearchOpen) {
getCurrentFragment()?.onSearchQueryChanged(main_menu.getCurrentQuery())
getFavoritesFragment()?.refreshItems {
if (binding.mainMenu.isSearchOpen) {
getCurrentFragment()?.onSearchQueryChanged(binding.mainMenu.getCurrentQuery())
}
}
contacts_fragment?.refreshItems {
if (main_menu.isSearchOpen) {
getCurrentFragment()?.onSearchQueryChanged(main_menu.getCurrentQuery())
getContactsFragment()?.refreshItems {
if (binding.mainMenu.isSearchOpen) {
getCurrentFragment()?.onSearchQueryChanged(binding.mainMenu.getCurrentQuery())
}
}
recents_fragment.refreshItems{
if (main_menu.isSearchOpen) {
getCurrentFragment()?.onSearchQueryChanged(main_menu.getCurrentQuery())
getRecentsFragment()?.refreshItems {
if (binding.mainMenu.isSearchOpen) {
getCurrentFragment()?.onSearchQueryChanged(binding.mainMenu.getCurrentQuery())
}
}
}
}
fun cacheContacts(contacts: List<Contact>) {
try {
cachedContacts.clear()

View File

@ -2,42 +2,58 @@ package com.simplemobiletools.dialer.activities
import android.os.Bundle
import com.google.gson.Gson
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
import com.simplemobiletools.commons.extensions.getMyContactsCursor
import com.simplemobiletools.commons.extensions.updateTextColors
import com.simplemobiletools.commons.extensions.viewBinding
import com.simplemobiletools.commons.helpers.ContactsHelper
import com.simplemobiletools.commons.helpers.MyContactsContentProvider
import com.simplemobiletools.commons.helpers.NavigationIcon
import com.simplemobiletools.commons.models.PhoneNumber
import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.commons.models.contacts.Contact
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.adapters.SpeedDialAdapter
import com.simplemobiletools.dialer.databinding.ActivityManageSpeedDialBinding
import com.simplemobiletools.dialer.dialogs.SelectContactDialog
import com.simplemobiletools.dialer.extensions.config
import com.simplemobiletools.dialer.interfaces.RemoveSpeedDialListener
import com.simplemobiletools.dialer.models.SpeedDial
import kotlinx.android.synthetic.main.activity_manage_speed_dial.*
class ManageSpeedDialActivity : SimpleActivity(), RemoveSpeedDialListener {
private var allContacts = ArrayList<Contact>()
private var speedDialValues = ArrayList<SpeedDial>()
private val binding by viewBinding(ActivityManageSpeedDialBinding::inflate)
private var allContacts = mutableListOf<Contact>()
private var speedDialValues = mutableListOf<SpeedDial>()
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_manage_speed_dial)
setContentView(binding.root)
updateMaterialActivityViews(manage_speed_dial_coordinator, manage_speed_dial_holder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(manage_speed_dial_scrollview, manage_speed_dial_toolbar)
binding.apply {
updateMaterialActivityViews(manageSpeedDialCoordinator, manageSpeedDialHolder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(manageSpeedDialScrollview, manageSpeedDialToolbar)
}
speedDialValues = config.getSpeedDialValues()
updateAdapter()
ContactsHelper(this).getContacts(false) { contacts ->
allContacts = contacts
ContactsHelper(this).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
allContacts.addAll(contacts)
val privateCursor = getMyContactsCursor(false, true)
val privateContacts = MyContactsContentProvider.getContacts(this, privateCursor)
allContacts.addAll(privateContacts)
allContacts.sort()
}
updateTextColors(manage_speed_dial_scrollview)
updateTextColors(binding.manageSpeedDialScrollview)
}
override fun onResume() {
super.onResume()
setupToolbar(manage_speed_dial_toolbar, NavigationIcon.Arrow)
setupToolbar(binding.manageSpeedDialToolbar, NavigationIcon.Arrow)
}
override fun onStop() {
@ -46,21 +62,38 @@ class ManageSpeedDialActivity : SimpleActivity(), RemoveSpeedDialListener {
}
private fun updateAdapter() {
SpeedDialAdapter(this, speedDialValues, this, speed_dial_list) {
SpeedDialAdapter(this, speedDialValues, this, binding.speedDialList) {
val clickedContact = it as SpeedDial
if (allContacts.isEmpty()) {
return@SpeedDialAdapter
}
SelectContactDialog(this, allContacts) { selectedContact ->
speedDialValues.first { it.id == clickedContact.id }.apply {
displayName = selectedContact.getNameToDisplay()
number = selectedContact.phoneNumbers.first().normalizedNumber
if (selectedContact.phoneNumbers.size > 1) {
val radioItems = selectedContact.phoneNumbers.mapIndexed { index, item ->
RadioItem(index, item.normalizedNumber, item)
}
val userPhoneNumbersList = selectedContact.phoneNumbers.map { it.value }
val checkedItemId = userPhoneNumbersList.indexOf(clickedContact.number)
RadioGroupDialog(this, ArrayList(radioItems), checkedItemId = checkedItemId) { selectedValue ->
val selectedNumber = selectedValue as PhoneNumber
speedDialValues.first { it.id == clickedContact.id }.apply {
displayName = selectedContact.getNameToDisplay()
number = selectedNumber.normalizedNumber
}
updateAdapter()
}
} else {
speedDialValues.first { it.id == clickedContact.id }.apply {
displayName = selectedContact.getNameToDisplay()
number = selectedContact.phoneNumbers.first().normalizedNumber
}
updateAdapter()
}
updateAdapter()
}
}.apply {
speed_dial_list.adapter = this
binding.speedDialList.adapter = this
}
}

View File

@ -2,9 +2,11 @@ package com.simplemobiletools.dialer.activities
import android.annotation.TargetApi
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.view.Menu
import androidx.activity.result.contract.ActivityResultContracts
import com.simplemobiletools.commons.activities.ManageBlockedNumbersActivity
import com.simplemobiletools.commons.dialogs.ChangeDateTimeFormatDialog
import com.simplemobiletools.commons.dialogs.FeatureLockedDialog
@ -13,26 +15,54 @@ import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.databinding.ActivitySettingsBinding
import com.simplemobiletools.dialer.dialogs.ExportCallHistoryDialog
import com.simplemobiletools.dialer.dialogs.ManageVisibleTabsDialog
import com.simplemobiletools.dialer.extensions.config
import kotlinx.android.synthetic.main.activity_settings.*
import com.simplemobiletools.dialer.helpers.RecentsHelper
import com.simplemobiletools.dialer.models.RecentCall
import kotlinx.serialization.SerializationException
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.util.*
import kotlin.system.exitProcess
class SettingsActivity : SimpleActivity() {
companion object {
private const val CALL_HISTORY_FILE_TYPE = "application/json"
}
private val binding by viewBinding(ActivitySettingsBinding::inflate)
private val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
if (uri != null) {
toast(R.string.importing)
importCallHistory(uri)
}
}
private val saveDocument = registerForActivityResult(ActivityResultContracts.CreateDocument(CALL_HISTORY_FILE_TYPE)) { uri ->
if (uri != null) {
toast(R.string.exporting)
RecentsHelper(this).getRecentCalls(false, Int.MAX_VALUE) { recents ->
exportCallHistory(recents, uri)
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_settings)
setContentView(binding.root)
updateMaterialActivityViews(settings_coordinator, settings_holder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(settings_nested_scrollview, settings_toolbar)
binding.apply {
updateMaterialActivityViews(settingsCoordinator, settingsHolder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(settingsNestedScrollview, settingsToolbar)
}
}
override fun onResume() {
super.onResume()
setupToolbar(settings_toolbar, NavigationIcon.Arrow)
setupToolbar(binding.settingsToolbar, NavigationIcon.Arrow)
setupPurchaseThankYou()
setupCustomizeColors()
@ -54,15 +84,20 @@ class SettingsActivity : SimpleActivity() {
setupDisableProximitySensor()
setupDisableSwipeToAnswer()
setupAlwaysShowFullscreen()
updateTextColors(settings_holder)
setupCallsExport()
setupCallsImport()
updateTextColors(binding.settingsHolder)
arrayOf(
settings_color_customization_section_label,
settings_general_settings_label,
settings_startup_label,
settings_calls_label
).forEach {
it.setTextColor(getProperPrimaryColor())
binding.apply {
arrayOf(
settingsColorCustomizationSectionLabel,
settingsGeneralSettingsLabel,
settingsStartupLabel,
settingsCallsLabel,
settingsMigrationSectionLabel
).forEach {
it.setTextColor(getProperPrimaryColor())
}
}
}
@ -72,55 +107,61 @@ class SettingsActivity : SimpleActivity() {
}
private fun setupPurchaseThankYou() {
settings_purchase_thank_you_holder.beGoneIf(isOrWasThankYouInstalled())
settings_purchase_thank_you_holder.setOnClickListener {
binding.settingsPurchaseThankYouHolder.beGoneIf(isOrWasThankYouInstalled())
binding.settingsPurchaseThankYouHolder.setOnClickListener {
launchPurchaseThankYouIntent()
}
}
private fun setupCustomizeColors() {
settings_color_customization_label.text = getCustomizeColorsString()
settings_color_customization_holder.setOnClickListener {
binding.settingsColorCustomizationLabel.text = getCustomizeColorsString()
binding.settingsColorCustomizationHolder.setOnClickListener {
handleCustomizeColorsClick()
}
}
private fun setupUseEnglish() {
settings_use_english_holder.beVisibleIf((config.wasUseEnglishToggled || Locale.getDefault().language != "en") && !isTiramisuPlus())
settings_use_english.isChecked = config.useEnglish
settings_use_english_holder.setOnClickListener {
settings_use_english.toggle()
config.useEnglish = settings_use_english.isChecked
exitProcess(0)
binding.apply {
settingsUseEnglishHolder.beVisibleIf((config.wasUseEnglishToggled || Locale.getDefault().language != "en") && !isTiramisuPlus())
settingsUseEnglish.isChecked = config.useEnglish
settingsUseEnglishHolder.setOnClickListener {
settingsUseEnglish.toggle()
config.useEnglish = settingsUseEnglish.isChecked
exitProcess(0)
}
}
}
private fun setupLanguage() {
settings_language.text = Locale.getDefault().displayLanguage
settings_language_holder.beVisibleIf(isTiramisuPlus())
settings_language_holder.setOnClickListener {
launchChangeAppLanguageIntent()
binding.apply {
settingsLanguage.text = Locale.getDefault().displayLanguage
settingsLanguageHolder.beVisibleIf(isTiramisuPlus())
settingsLanguageHolder.setOnClickListener {
launchChangeAppLanguageIntent()
}
}
}
// support for device-wise blocking came on Android 7, rely only on that
@TargetApi(Build.VERSION_CODES.N)
private fun setupManageBlockedNumbers() {
settings_manage_blocked_numbers_label.text = addLockedLabelIfNeeded(R.string.manage_blocked_numbers)
settings_manage_blocked_numbers_holder.beVisibleIf(isNougatPlus())
settings_manage_blocked_numbers_holder.setOnClickListener {
if (isOrWasThankYouInstalled()) {
Intent(this, ManageBlockedNumbersActivity::class.java).apply {
startActivity(this)
binding.apply {
settingsManageBlockedNumbersLabel.text = addLockedLabelIfNeeded(R.string.manage_blocked_numbers)
settingsManageBlockedNumbersHolder.beVisibleIf(isNougatPlus())
settingsManageBlockedNumbersHolder.setOnClickListener {
if (isOrWasThankYouInstalled()) {
Intent(this@SettingsActivity, ManageBlockedNumbersActivity::class.java).apply {
startActivity(this)
}
} else {
FeatureLockedDialog(this@SettingsActivity) { }
}
} else {
FeatureLockedDialog(this) { }
}
}
}
private fun setupManageSpeedDial() {
settings_manage_speed_dial_holder.setOnClickListener {
binding.settingsManageSpeedDialHolder.setOnClickListener {
Intent(this, ManageSpeedDialActivity::class.java).apply {
startActivity(this)
}
@ -128,14 +169,14 @@ class SettingsActivity : SimpleActivity() {
}
private fun setupChangeDateTimeFormat() {
settings_change_date_time_format_holder.setOnClickListener {
binding.settingsChangeDateTimeFormatHolder.setOnClickListener {
ChangeDateTimeFormatDialog(this) {}
}
}
private fun setupFontSize() {
settings_font_size.text = getFontSizeText()
settings_font_size_holder.setOnClickListener {
binding.settingsFontSize.text = getFontSizeText()
binding.settingsFontSizeHolder.setOnClickListener {
val items = arrayListOf(
RadioItem(FONT_SIZE_SMALL, getString(R.string.small)),
RadioItem(FONT_SIZE_MEDIUM, getString(R.string.medium)),
@ -145,20 +186,20 @@ class SettingsActivity : SimpleActivity() {
RadioGroupDialog(this@SettingsActivity, items, config.fontSize) {
config.fontSize = it as Int
settings_font_size.text = getFontSizeText()
binding.settingsFontSize.text = getFontSizeText()
}
}
}
private fun setupManageShownTabs() {
settings_manage_tabs_holder.setOnClickListener {
binding.settingsManageTabsHolder.setOnClickListener {
ManageVisibleTabsDialog(this)
}
}
private fun setupDefaultTab() {
settings_default_tab.text = getDefaultTabText()
settings_default_tab_holder.setOnClickListener {
binding.settingsDefaultTab.text = getDefaultTabText()
binding.settingsDefaultTabHolder.setOnClickListener {
val items = arrayListOf(
RadioItem(TAB_CONTACTS, getString(R.string.contacts_tab)),
RadioItem(TAB_FAVORITES, getString(R.string.favorites_tab)),
@ -168,7 +209,7 @@ class SettingsActivity : SimpleActivity() {
RadioGroupDialog(this@SettingsActivity, items, config.defaultTab) {
config.defaultTab = it as Int
settings_default_tab.text = getDefaultTabText()
binding.settingsDefaultTab.text = getDefaultTabText()
}
}
}
@ -183,82 +224,159 @@ class SettingsActivity : SimpleActivity() {
)
private fun setupDialPadOpen() {
settings_open_dialpad_at_launch.isChecked = config.openDialPadAtLaunch
settings_open_dialpad_at_launch_holder.setOnClickListener {
settings_open_dialpad_at_launch.toggle()
config.openDialPadAtLaunch = settings_open_dialpad_at_launch.isChecked
binding.apply {
settingsOpenDialpadAtLaunch.isChecked = config.openDialPadAtLaunch
settingsOpenDialpadAtLaunchHolder.setOnClickListener {
settingsOpenDialpadAtLaunch.toggle()
config.openDialPadAtLaunch = settingsOpenDialpadAtLaunch.isChecked
}
}
}
private fun setupGroupSubsequentCalls() {
settings_group_subsequent_calls.isChecked = config.groupSubsequentCalls
settings_group_subsequent_calls_holder.setOnClickListener {
settings_group_subsequent_calls.toggle()
config.groupSubsequentCalls = settings_group_subsequent_calls.isChecked
binding.apply {
settingsGroupSubsequentCalls.isChecked = config.groupSubsequentCalls
settingsGroupSubsequentCallsHolder.setOnClickListener {
settingsGroupSubsequentCalls.toggle()
config.groupSubsequentCalls = settingsGroupSubsequentCalls.isChecked
}
}
}
private fun setupStartNameWithSurname() {
settings_start_name_with_surname.isChecked = config.startNameWithSurname
settings_start_name_with_surname_holder.setOnClickListener {
settings_start_name_with_surname.toggle()
config.startNameWithSurname = settings_start_name_with_surname.isChecked
binding.apply {
settingsStartNameWithSurname.isChecked = config.startNameWithSurname
settingsStartNameWithSurnameHolder.setOnClickListener {
settingsStartNameWithSurname.toggle()
config.startNameWithSurname = settingsStartNameWithSurname.isChecked
}
}
}
private fun setupDialpadVibrations() {
settings_dialpad_vibration.isChecked = config.dialpadVibration
settings_dialpad_vibration_holder.setOnClickListener {
settings_dialpad_vibration.toggle()
config.dialpadVibration = settings_dialpad_vibration.isChecked
binding.apply {
settingsDialpadVibration.isChecked = config.dialpadVibration
settingsDialpadVibrationHolder.setOnClickListener {
settingsDialpadVibration.toggle()
config.dialpadVibration = settingsDialpadVibration.isChecked
}
}
}
private fun setupDialpadNumbers() {
settings_hide_dialpad_numbers.isChecked = config.hideDialpadNumbers
settings_hide_dialpad_numbers_holder.setOnClickListener {
settings_hide_dialpad_numbers.toggle()
config.hideDialpadNumbers = settings_hide_dialpad_numbers.isChecked
binding.apply {
settingsHideDialpadNumbers.isChecked = config.hideDialpadNumbers
settingsHideDialpadNumbersHolder.setOnClickListener {
settingsHideDialpadNumbers.toggle()
config.hideDialpadNumbers = settingsHideDialpadNumbers.isChecked
}
}
}
private fun setupDialpadBeeps() {
settings_dialpad_beeps.isChecked = config.dialpadBeeps
settings_dialpad_beeps_holder.setOnClickListener {
settings_dialpad_beeps.toggle()
config.dialpadBeeps = settings_dialpad_beeps.isChecked
binding.apply {
settingsDialpadBeeps.isChecked = config.dialpadBeeps
settingsDialpadBeepsHolder.setOnClickListener {
settingsDialpadBeeps.toggle()
config.dialpadBeeps = settingsDialpadBeeps.isChecked
}
}
}
private fun setupShowCallConfirmation() {
settings_show_call_confirmation.isChecked = config.showCallConfirmation
settings_show_call_confirmation_holder.setOnClickListener {
settings_show_call_confirmation.toggle()
config.showCallConfirmation = settings_show_call_confirmation.isChecked
binding.apply {
settingsShowCallConfirmation.isChecked = config.showCallConfirmation
settingsShowCallConfirmationHolder.setOnClickListener {
settingsShowCallConfirmation.toggle()
config.showCallConfirmation = settingsShowCallConfirmation.isChecked
}
}
}
private fun setupDisableProximitySensor() {
settings_disable_proximity_sensor.isChecked = config.disableProximitySensor
settings_disable_proximity_sensor_holder.setOnClickListener {
settings_disable_proximity_sensor.toggle()
config.disableProximitySensor = settings_disable_proximity_sensor.isChecked
binding.apply {
settingsDisableProximitySensor.isChecked = config.disableProximitySensor
settingsDisableProximitySensorHolder.setOnClickListener {
settingsDisableProximitySensor.toggle()
config.disableProximitySensor = settingsDisableProximitySensor.isChecked
}
}
}
private fun setupDisableSwipeToAnswer() {
settings_disable_swipe_to_answer.isChecked = config.disableSwipeToAnswer
settings_disable_swipe_to_answer_holder.setOnClickListener {
settings_disable_swipe_to_answer.toggle()
config.disableSwipeToAnswer = settings_disable_swipe_to_answer.isChecked
binding.apply {
settingsDisableSwipeToAnswer.isChecked = config.disableSwipeToAnswer
settingsDisableSwipeToAnswerHolder.setOnClickListener {
settingsDisableSwipeToAnswer.toggle()
config.disableSwipeToAnswer = settingsDisableSwipeToAnswer.isChecked
}
}
}
private fun setupAlwaysShowFullscreen() {
settings_always_show_fullscreen.isChecked = config.alwaysShowFullscreen
settings_always_show_fullscreen_holder.setOnClickListener {
settings_always_show_fullscreen.toggle()
config.alwaysShowFullscreen = settings_always_show_fullscreen.isChecked
binding.apply {
settingsAlwaysShowFullscreen.isChecked = config.alwaysShowFullscreen
settingsAlwaysShowFullscreenHolder.setOnClickListener {
settingsAlwaysShowFullscreen.toggle()
config.alwaysShowFullscreen = settingsAlwaysShowFullscreen.isChecked
}
}
}
private fun setupCallsExport() {
binding.settingsExportCallsHolder.setOnClickListener {
ExportCallHistoryDialog(this) { filename ->
saveDocument.launch(filename)
}
}
}
private fun setupCallsImport() {
binding.settingsImportCallsHolder.setOnClickListener {
getContent.launch(CALL_HISTORY_FILE_TYPE)
}
}
private fun importCallHistory(uri: Uri) {
try {
val jsonString = contentResolver.openInputStream(uri)!!.use { inputStream ->
inputStream.bufferedReader().readText()
}
val objects = Json.decodeFromString<List<RecentCall>>(jsonString)
if (objects.isEmpty()) {
toast(R.string.no_entries_for_importing)
return
}
RecentsHelper(this).restoreRecentCalls(this, objects) {
toast(R.string.importing_successful)
}
} catch (_: SerializationException) {
toast(R.string.invalid_file_format)
} catch (_: IllegalArgumentException) {
toast(R.string.invalid_file_format)
} catch (e: Exception) {
showErrorToast(e)
}
}
private fun exportCallHistory(recents: List<RecentCall>, uri: Uri) {
if (recents.isEmpty()) {
toast(R.string.no_entries_for_exporting)
} else {
try {
val outputStream = contentResolver.openOutputStream(uri)!!
val jsonString = Json.encodeToString(recents)
outputStream.use {
it.write(jsonString.toByteArray())
}
toast(R.string.exporting_successful)
} catch (e: Exception) {
showErrorToast(e)
}
}
}
}

View File

@ -11,9 +11,9 @@ import com.simplemobiletools.commons.helpers.SimpleContactsHelper
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.activities.SimpleActivity
import com.simplemobiletools.dialer.databinding.ItemConferenceCallBinding
import com.simplemobiletools.dialer.extensions.hasCapability
import com.simplemobiletools.dialer.helpers.getCallContact
import kotlinx.android.synthetic.main.item_conference_call.view.*
class ConferenceCallsAdapter(
activity: SimpleActivity, recyclerView: MyRecyclerView, val data: ArrayList<Call>, itemClick: (Any) -> Unit
@ -39,55 +39,63 @@ class ConferenceCallsAdapter(
override fun prepareActionMode(menu: Menu) {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_conference_call, parent)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return createViewHolder(ItemConferenceCallBinding.inflate(layoutInflater, parent, false).root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val call = data[position]
holder.bindView(call, allowSingleClick = false, allowLongClick = false) { itemView, _ ->
getCallContact(itemView.context, call) { callContact ->
itemView.post {
itemView.item_conference_call_name.text = callContact.name.ifEmpty { itemView.context.getString(R.string.unknown_caller) }
SimpleContactsHelper(activity).loadContactImage(
callContact.photoUri,
itemView.item_conference_call_image,
callContact.name,
activity.getDrawable(R.drawable.ic_person_vector)
)
ItemConferenceCallBinding.bind(itemView).apply {
getCallContact(itemView.context, call) { callContact ->
root.post {
itemConferenceCallName.text = callContact.name.ifEmpty { itemView.context.getString(R.string.unknown_caller) }
SimpleContactsHelper(activity).loadContactImage(
callContact.photoUri,
itemConferenceCallImage,
callContact.name,
activity.getDrawable(R.drawable.ic_person_vector)
)
}
}
}
val canSeparate = call.hasCapability(Call.Details.CAPABILITY_SEPARATE_FROM_CONFERENCE)
val canDisconnect = call.hasCapability(Call.Details.CAPABILITY_DISCONNECT_FROM_CONFERENCE)
itemView.item_conference_call_split.isEnabled = canSeparate
itemView.item_conference_call_split.alpha = if (canSeparate) 1.0f else LOWER_ALPHA
itemView.item_conference_call_split.setOnClickListener {
call.splitFromConference()
data.removeAt(position)
notifyItemRemoved(position)
if (data.size == 1) {
activity.finish()
val canSeparate = call.hasCapability(Call.Details.CAPABILITY_SEPARATE_FROM_CONFERENCE)
val canDisconnect = call.hasCapability(Call.Details.CAPABILITY_DISCONNECT_FROM_CONFERENCE)
itemConferenceCallSplit.isEnabled = canSeparate
itemConferenceCallSplit.alpha = if (canSeparate) 1.0f else LOWER_ALPHA
itemConferenceCallSplit.setOnClickListener {
call.splitFromConference()
data.removeAt(position)
notifyItemRemoved(position)
if (data.size == 1) {
activity.finish()
}
}
}
itemView.item_conference_call_split.setOnLongClickListener {
if (!it.contentDescription.isNullOrEmpty()) {
itemView.context.toast(it.contentDescription.toString())
itemConferenceCallSplit.setOnLongClickListener {
if (!it.contentDescription.isNullOrEmpty()) {
root.context.toast(it.contentDescription.toString())
}
true
}
true
}
itemView.item_conference_call_end.isEnabled = canDisconnect
itemView.item_conference_call_end.alpha = if (canDisconnect) 1.0f else LOWER_ALPHA
itemView.item_conference_call_end.setOnClickListener {
call.disconnect()
data.removeAt(position)
notifyItemRemoved(position)
if (data.size == 1) {
activity.finish()
itemConferenceCallEnd.isEnabled = canDisconnect
itemConferenceCallEnd.alpha = if (canDisconnect) 1.0f else LOWER_ALPHA
itemConferenceCallEnd.setOnClickListener {
call.disconnect()
data.removeAt(position)
notifyItemRemoved(position)
if (data.size == 1) {
activity.finish()
}
}
}
itemView.item_conference_call_end.setOnLongClickListener {
if (!it.contentDescription.isNullOrEmpty()) {
itemView.context.toast(it.contentDescription.toString())
itemConferenceCallEnd.setOnLongClickListener {
if (!it.contentDescription.isNullOrEmpty()) {
root.context.toast(it.contentDescription.toString())
}
true
}
true
}
}
bindViewHolder(holder)
@ -96,7 +104,9 @@ class ConferenceCallsAdapter(
override fun onViewRecycled(holder: ViewHolder) {
super.onViewRecycled(holder)
if (!activity.isDestroyed && !activity.isFinishing) {
Glide.with(activity).clear(holder.itemView.item_conference_call_image)
ItemConferenceCallBinding.bind(holder.itemView).apply {
Glide.with(activity).clear(itemConferenceCallImage)
}
}
}
}

View File

@ -7,24 +7,22 @@ import android.graphics.drawable.Icon
import android.net.Uri
import android.text.TextUtils
import android.util.TypedValue
import android.view.Menu
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.view.*
import android.widget.ImageView
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
import com.bumptech.glide.Glide
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.databinding.ItemContactWithoutNumberBinding
import com.simplemobiletools.commons.databinding.ItemContactWithoutNumberGridBinding
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.dialogs.FeatureLockedDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.PERMISSION_CALL_PHONE
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_CONTACTS
import com.simplemobiletools.commons.helpers.SimpleContactsHelper
import com.simplemobiletools.commons.helpers.isOreoPlus
import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.interfaces.ItemMoveCallback
import com.simplemobiletools.commons.interfaces.ItemTouchHelperContract
import com.simplemobiletools.commons.interfaces.StartReorderDragListener
@ -41,26 +39,35 @@ import java.util.*
class ContactsAdapter(
activity: SimpleActivity,
var contacts: ArrayList<Contact>,
var contacts: MutableList<Contact>,
recyclerView: MyRecyclerView,
val refreshItemsListener: RefreshItemsListener? = null,
highlightText: String = "",
val showDeleteButton: Boolean = true,
private val refreshItemsListener: RefreshItemsListener? = null,
var viewType: Int = VIEW_TYPE_LIST,
private val showDeleteButton: Boolean = true,
private val enableDrag: Boolean = false,
private val allowLongClick: Boolean = true,
itemClick: (Any) -> Unit
) : MyRecyclerViewAdapter(activity, recyclerView, itemClick), ItemTouchHelperContract {
) : MyRecyclerViewAdapter(activity, recyclerView, itemClick),
ItemTouchHelperContract, MyRecyclerView.MyZoomListener {
private var textToHighlight = highlightText
private var fontSize = activity.getTextSize()
var fontSize: Float = activity.getTextSize()
private var touchHelper: ItemTouchHelper? = null
private var startReorderDragListener: StartReorderDragListener? = null
var onDragEndListener: (() -> Unit)? = null
var onSpanCountListener: (Int) -> Unit = {}
init {
setupDragListener(true)
if (recyclerView.layoutManager is GridLayoutManager) {
setupZoomListener(this)
}
if (enableDrag) {
touchHelper = ItemTouchHelper(ItemMoveCallback(this))
touchHelper = ItemTouchHelper(ItemMoveCallback(this, viewType == VIEW_TYPE_GRID))
touchHelper!!.attachToRecyclerView(recyclerView)
startReorderDragListener = object : StartReorderDragListener {
@ -81,12 +88,16 @@ class ContactsAdapter(
menu.apply {
findItem(R.id.cab_call_sim_1).isVisible = hasMultipleSIMs && isOneItemSelected
findItem(R.id.cab_call_sim_2).isVisible = hasMultipleSIMs && isOneItemSelected
findItem(R.id.cab_remove_default_sim).isVisible = isOneItemSelected && activity.config.getCustomSIM(selectedNumber) != ""
findItem(R.id.cab_remove_default_sim).isVisible = isOneItemSelected && (activity.config.getCustomSIM(selectedNumber) ?: "") != ""
findItem(R.id.cab_delete).isVisible = showDeleteButton
findItem(R.id.cab_create_shortcut).title = activity.addLockedLabelIfNeeded(R.string.create_shortcut)
findItem(R.id.cab_create_shortcut).isVisible = isOneItemSelected && isOreoPlus()
findItem(R.id.cab_view_details).isVisible = isOneItemSelected
findItem(R.id.cab_block_unblock_contact).isVisible = isOneItemSelected && isNougatPlus()
getCabBlockContactTitle { title ->
findItem(R.id.cab_block_unblock_contact).title = title
}
}
}
@ -96,6 +107,7 @@ class ContactsAdapter(
}
when (id) {
R.id.cab_block_unblock_contact -> tryBlockingUnblocking()
R.id.cab_call_sim_1 -> callContact(true)
R.id.cab_call_sim_2 -> callContact(false)
R.id.cab_remove_default_sim -> removeDefaultSIM()
@ -123,21 +135,94 @@ class ContactsAdapter(
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_contact_without_number, parent)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = Binding.getByItemViewType(viewType).inflate(layoutInflater, parent, false)
return createViewHolder(binding.root)
}
override fun getItemViewType(position: Int): Int {
return viewType
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val contact = contacts[position]
holder.bindView(contact, true, true) { itemView, layoutPosition ->
setupView(itemView, contact, holder)
holder.bindView(contact, true, allowLongClick) { itemView, layoutPosition ->
val viewType = getItemViewType(position)
setupView(Binding.getByItemViewType(viewType).bind(itemView), contact, holder)
}
bindViewHolder(holder)
}
override fun getItemCount() = contacts.size
fun updateItems(newItems: ArrayList<Contact>, highlightText: String = "") {
private fun getCabBlockContactTitle(callback: (String) -> Unit) {
val contact = getSelectedItems().firstOrNull() ?: return callback("")
activity.isContactBlocked(contact) { blocked ->
val cabItemTitleRes = if (blocked) {
R.string.unblock_contact
} else {
R.string.block_contact
}
callback(activity.addLockedLabelIfNeeded(cabItemTitleRes))
}
}
private fun tryBlockingUnblocking() {
val contact = getSelectedItems().firstOrNull() ?: return
if (activity.isOrWasThankYouInstalled()) {
activity.isContactBlocked(contact) { blocked ->
if (blocked) {
tryUnblocking(contact)
} else {
tryBlocking(contact)
}
}
} else {
FeatureLockedDialog(activity) { }
}
}
private fun tryBlocking(contact: Contact) {
askConfirmBlock(contact) { contactBlocked ->
val resultMsg = if (contactBlocked) {
R.string.block_contact_success
} else {
R.string.block_contact_fail
}
activity.toast(resultMsg)
finishActMode()
}
}
private fun tryUnblocking(contact: Contact) {
val contactUnblocked = activity.unblockContact(contact)
val resultMsg = if (contactUnblocked) {
R.string.unblock_contact_success
} else {
R.string.unblock_contact_fail
}
activity.toast(resultMsg)
finishActMode()
}
private fun askConfirmBlock(contact: Contact, callback: (Boolean) -> Unit) {
val baseString = R.string.block_confirmation
val question = String.format(resources.getString(baseString), contact.name)
ConfirmationDialog(activity, question) {
val contactBlocked = activity.blockContact(contact)
callback(contactBlocked)
}
}
fun updateItems(newItems: List<Contact>, highlightText: String = "") {
if (newItems.hashCode() != contacts.hashCode()) {
contacts = newItems.clone() as ArrayList<Contact>
contacts = ArrayList(newItems)
textToHighlight = highlightText
notifyDataSetChanged()
finishActMode()
@ -224,9 +309,7 @@ class ContactsAdapter(
private fun getSelectedItems() = contacts.filter { selectedKeys.contains(it.rawId) } as ArrayList<Contact>
private fun getSelectedPhoneNumber(): String? {
val numbers = getSelectedItems().firstOrNull()?.phoneNumbers
val primaryNumber = numbers?.firstOrNull { it.isPrimary }
return primaryNumber?.normalizedNumber ?: numbers?.firstOrNull()?.normalizedNumber
return getSelectedItems().firstOrNull()?.getPrimaryNumber()
}
private fun tryCreateShortcut() {
@ -247,7 +330,7 @@ class ContactsAdapter(
activity.handlePermission(PERMISSION_CALL_PHONE) { hasPermission ->
val action = if (hasPermission) Intent.ACTION_CALL else Intent.ACTION_DIAL
val intent = Intent(action).apply {
data = Uri.fromParts("tel", contact.phoneNumbers.first().normalizedNumber, null)
data = Uri.fromParts("tel", getSelectedPhoneNumber(), null)
}
val shortcut = ShortcutInfo.Builder(activity, contact.hashCode().toString())
@ -266,14 +349,17 @@ class ContactsAdapter(
override fun onViewRecycled(holder: ViewHolder) {
super.onViewRecycled(holder)
if (!activity.isDestroyed && !activity.isFinishing) {
Glide.with(activity).clear(holder.itemView.findViewById<ImageView>(R.id.item_contact_image))
Binding.getByItemViewType(holder.itemViewType).bind(holder.itemView).apply {
Glide.with(activity).clear(itemContactImage)
}
}
}
private fun setupView(view: View, contact: Contact, holder: ViewHolder) {
view.apply {
findViewById<FrameLayout>(R.id.item_contact_frame).isSelected = selectedKeys.contains(contact.rawId)
findViewById<TextView>(R.id.item_contact_name).apply {
private fun setupView(binding: ItemViewBinding, contact: Contact, holder: ViewHolder) {
binding.apply {
root.setupViewBackground(activity)
itemContactFrame.isSelected = selectedKeys.contains(contact.rawId)
itemContactName.apply {
setTextColor(textColor)
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
@ -287,9 +373,8 @@ class ContactsAdapter(
}
}
val dragIcon = findViewById<ImageView>(R.id.drag_handle_icon)
if (enableDrag && textToHighlight.isEmpty()) {
dragIcon.apply {
dragHandleIcon.apply {
beVisibleIf(selectedKeys.isNotEmpty())
applyColorFilter(textColor)
setOnTouchListener { _, event ->
@ -300,14 +385,14 @@ class ContactsAdapter(
}
}
} else {
dragIcon.apply {
dragHandleIcon.apply {
beGone()
setOnTouchListener(null)
}
}
if (!activity.isDestroyed) {
SimpleContactsHelper(context).loadContactImage(contact.photoUri, findViewById(R.id.item_contact_image), contact.getNameToDisplay())
SimpleContactsHelper(root.context).loadContactImage(contact.photoUri, itemContactImage, contact.getNameToDisplay())
}
}
}
@ -333,4 +418,86 @@ class ContactsAdapter(
override fun onRowClear(myViewHolder: ViewHolder?) {
onDragEndListener?.invoke()
}
override fun zoomIn() {
val layoutManager = recyclerView.layoutManager
if (layoutManager is GridLayoutManager) {
val currentSpanCount = layoutManager.spanCount
val newSpanCount = (currentSpanCount - 1).coerceIn(1, CONTACTS_GRID_MAX_COLUMNS_COUNT)
layoutManager.spanCount = newSpanCount
recyclerView.requestLayout()
onSpanCountListener(newSpanCount)
}
}
override fun zoomOut() {
val layoutManager = recyclerView.layoutManager
if (layoutManager is GridLayoutManager) {
val currentSpanCount = layoutManager.spanCount
val newSpanCount = (currentSpanCount + 1).coerceIn(1, CONTACTS_GRID_MAX_COLUMNS_COUNT)
layoutManager.spanCount = newSpanCount
recyclerView.requestLayout()
onSpanCountListener(newSpanCount)
}
}
private sealed interface Binding {
companion object {
fun getByItemViewType(viewType: Int): Binding {
return when (viewType) {
VIEW_TYPE_GRID -> ItemContactGrid
else -> ItemContact
}
}
}
fun inflate(layoutInflater: LayoutInflater, viewGroup: ViewGroup, attachToRoot: Boolean): ItemViewBinding
fun bind(view: View): ItemViewBinding
data object ItemContactGrid : Binding {
override fun inflate(layoutInflater: LayoutInflater, viewGroup: ViewGroup, attachToRoot: Boolean): ItemViewBinding {
return ItemContactGridBindingAdapter(ItemContactWithoutNumberGridBinding.inflate(layoutInflater, viewGroup, attachToRoot))
}
override fun bind(view: View): ItemViewBinding {
return ItemContactGridBindingAdapter(ItemContactWithoutNumberGridBinding.bind(view))
}
}
data object ItemContact : Binding {
override fun inflate(layoutInflater: LayoutInflater, viewGroup: ViewGroup, attachToRoot: Boolean): ItemViewBinding {
return ItemContactBindingAdapter(ItemContactWithoutNumberBinding.inflate(layoutInflater, viewGroup, attachToRoot))
}
override fun bind(view: View): ItemViewBinding {
return ItemContactBindingAdapter(ItemContactWithoutNumberBinding.bind(view))
}
}
}
private interface ItemViewBinding : ViewBinding {
val itemContactName: TextView
val itemContactImage: ImageView
val itemContactFrame: ConstraintLayout
val dragHandleIcon: ImageView
}
private class ItemContactGridBindingAdapter(val binding: ItemContactWithoutNumberGridBinding) : ItemViewBinding {
override val itemContactName = binding.itemContactName
override val itemContactImage = binding.itemContactImage
override val itemContactFrame = binding.itemContactFrame
override val dragHandleIcon = binding.dragHandleIcon
override fun getRoot(): View = binding.root
}
private class ItemContactBindingAdapter(val binding: ItemContactWithoutNumberBinding) : ItemViewBinding {
override val itemContactName = binding.itemContactName
override val itemContactImage = binding.itemContactImage
override val itemContactFrame = binding.itemContactFrame
override val dragHandleIcon = binding.dragHandleIcon
override fun getRoot(): View = binding.root
}
}

View File

@ -8,9 +8,8 @@ import com.simplemobiletools.commons.extensions.getProperPrimaryColor
import com.simplemobiletools.commons.extensions.getProperTextColor
import com.simplemobiletools.commons.helpers.SMT_PRIVATE
import com.simplemobiletools.commons.models.contacts.ContactSource
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.activities.SimpleActivity
import kotlinx.android.synthetic.main.item_filter_contact_source.view.*
import com.simplemobiletools.dialer.databinding.ItemFilterContactSourceBinding
class FilterContactSourcesAdapter(
val activity: SimpleActivity,
@ -45,8 +44,8 @@ class FilterContactSourcesAdapter(
fun getSelectedContactSources() = contactSources.filter { selectedKeys.contains(it.hashCode()) }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = activity.layoutInflater.inflate(R.layout.item_filter_contact_source, parent, false)
return ViewHolder(view)
val binding = ItemFilterContactSourceBinding.inflate(activity.layoutInflater, parent, false)
return ViewHolder(binding.root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
@ -59,16 +58,16 @@ class FilterContactSourcesAdapter(
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bindView(contactSource: ContactSource): View {
val isSelected = selectedKeys.contains(contactSource.hashCode())
itemView.apply {
filter_contact_source_checkbox.isChecked = isSelected
filter_contact_source_checkbox.setColors(activity.getProperTextColor(), activity.getProperPrimaryColor(), activity.getProperBackgroundColor())
ItemFilterContactSourceBinding.bind(itemView).apply {
filterContactSourceCheckbox.isChecked = isSelected
filterContactSourceCheckbox.setColors(activity.getProperTextColor(), activity.getProperPrimaryColor(), activity.getProperBackgroundColor())
val countText = if (contactSource.count >= 0) " (${contactSource.count})" else ""
val displayName = "${contactSource.publicName}$countText"
filter_contact_source_checkbox.text = displayName
filter_contact_source_holder.setOnClickListener { viewClicked(!isSelected, contactSource) }
}
filterContactSourceCheckbox.text = displayName
filterContactSourceHolder.setOnClickListener { viewClicked(!isSelected, contactSource) }
return itemView
return root
}
}
private fun viewClicked(select: Boolean, contactSource: ContactSource) {

View File

@ -19,16 +19,16 @@ import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.activities.MainActivity
import com.simplemobiletools.dialer.activities.SimpleActivity
import com.simplemobiletools.dialer.databinding.ItemRecentCallBinding
import com.simplemobiletools.dialer.dialogs.ShowGroupedCallsDialog
import com.simplemobiletools.dialer.extensions.*
import com.simplemobiletools.dialer.helpers.RecentsHelper
import com.simplemobiletools.dialer.interfaces.RefreshItemsListener
import com.simplemobiletools.dialer.models.RecentCall
import kotlinx.android.synthetic.main.item_recent_call.view.*
class RecentCallsAdapter(
activity: SimpleActivity,
var recentCalls: ArrayList<RecentCall>,
private var recentCalls: MutableList<RecentCall>,
recyclerView: MyRecyclerView,
private val refreshItemsListener: RefreshItemsListener?,
private val showOverflowMenu: Boolean,
@ -38,7 +38,7 @@ class RecentCallsAdapter(
private lateinit var outgoingCallIcon: Drawable
private lateinit var incomingCallIcon: Drawable
private lateinit var incomingMissedCallIcon: Drawable
private var fontSize = activity.getTextSize()
var fontSize: Float = activity.getTextSize()
private val areMultipleSIMsAvailable = activity.areMultipleSIMsAvailable()
private val redColor = resources.getColor(R.color.md_red_700)
private var textToHighlight = ""
@ -60,7 +60,7 @@ class RecentCallsAdapter(
menu.apply {
findItem(R.id.cab_call_sim_1).isVisible = hasMultipleSIMs && isOneItemSelected
findItem(R.id.cab_call_sim_2).isVisible = hasMultipleSIMs && isOneItemSelected
findItem(R.id.cab_remove_default_sim).isVisible = isOneItemSelected && activity.config.getCustomSIM(selectedNumber) != ""
findItem(R.id.cab_remove_default_sim).isVisible = isOneItemSelected && (activity.config.getCustomSIM(selectedNumber) ?: "") != ""
findItem(R.id.cab_block_number).title = activity.addLockedLabelIfNeeded(R.string.block_number)
findItem(R.id.cab_block_number).isVisible = isNougatPlus()
@ -103,12 +103,19 @@ class RecentCallsAdapter(
override fun onActionModeDestroyed() {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_recent_call, parent)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return createViewHolder(ItemRecentCallBinding.inflate(layoutInflater, parent, false).root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val recentCall = recentCalls[position]
holder.bindView(recentCall, refreshItemsListener != null, refreshItemsListener != null) { itemView, layoutPosition ->
setupView(itemView, recentCall)
holder.bindView(
any = recentCall,
allowSingleClick = refreshItemsListener != null && !recentCall.isUnknownNumber,
allowLongClick = refreshItemsListener != null && !recentCall.isUnknownNumber
) { itemView, _ ->
val binding = ItemRecentCallBinding.bind(itemView)
setupView(binding, recentCall)
}
bindViewHolder(holder)
}
@ -118,7 +125,9 @@ class RecentCallsAdapter(
override fun onViewRecycled(holder: ViewHolder) {
super.onViewRecycled(holder)
if (!activity.isDestroyed && !activity.isFinishing) {
Glide.with(activity).clear(holder.itemView.item_recents_image)
ItemRecentCallBinding.bind(holder.itemView).apply {
Glide.with(activity).clear(itemRecentsImage)
}
}
}
@ -236,8 +245,8 @@ class RecentCallsAdapter(
RecentsHelper(activity).removeRecentCalls(idsToRemove) {
recentCalls.removeAll(callsToRemove)
activity.runOnUiThread {
refreshItemsListener?.refreshItems()
if (recentCalls.isEmpty()) {
refreshItemsListener?.refreshItems()
finishActMode()
} else {
removeSelectedItems(positions)
@ -256,10 +265,11 @@ class RecentCallsAdapter(
}
}
fun updateItems(newItems: ArrayList<RecentCall>, highlightText: String = "") {
fun updateItems(newItems: List<RecentCall>, highlightText: String = "") {
if (newItems.hashCode() != recentCalls.hashCode()) {
recentCalls = newItems.clone() as ArrayList<RecentCall>
recentCalls = newItems.toMutableList()
textToHighlight = highlightText
recyclerView.resetItemCount()
notifyDataSetChanged()
finishActMode()
} else if (textToHighlight != highlightText) {
@ -272,9 +282,10 @@ class RecentCallsAdapter(
private fun getSelectedPhoneNumber() = getSelectedItems().firstOrNull()?.phoneNumber
private fun setupView(view: View, call: RecentCall) {
view.apply {
item_recents_holder.isSelected = selectedKeys.contains(call.id)
private fun setupView(binding: ItemRecentCallBinding, call: RecentCall) {
binding.apply {
val currentFontSize = fontSize
itemRecentsHolder.isSelected = selectedKeys.contains(call.id)
val name = findContactByCall(call)?.getNameToDisplay() ?: call.name
var nameToShow = SpannableString(name)
if (call.specificType.isNotEmpty()) {
@ -294,37 +305,37 @@ class RecentCallsAdapter(
nameToShow = SpannableString(nameToShow.toString().highlightTextPart(textToHighlight, properPrimaryColor))
}
item_recents_name.apply {
itemRecentsName.apply {
text = nameToShow
setTextColor(textColor)
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
setTextSize(TypedValue.COMPLEX_UNIT_PX, currentFontSize)
}
item_recents_date_time.apply {
itemRecentsDateTime.apply {
text = call.startTS.formatDateOrTime(context, refreshItemsListener != null, false)
setTextColor(if (call.type == Calls.MISSED_TYPE) redColor else textColor)
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.8f)
setTextSize(TypedValue.COMPLEX_UNIT_PX, currentFontSize * 0.8f)
}
item_recents_duration.apply {
itemRecentsDuration.apply {
text = call.duration.getFormattedDuration()
setTextColor(textColor)
beVisibleIf(call.type != Calls.MISSED_TYPE && call.type != Calls.REJECTED_TYPE && call.duration > 0)
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.8f)
setTextSize(TypedValue.COMPLEX_UNIT_PX, currentFontSize * 0.8f)
if (!showOverflowMenu) {
item_recents_duration.setPadding(0, 0, durationPadding, 0)
itemRecentsDuration.setPadding(0, 0, durationPadding, 0)
}
}
item_recents_sim_image.beVisibleIf(areMultipleSIMsAvailable && call.simID != -1)
item_recents_sim_id.beVisibleIf(areMultipleSIMsAvailable && call.simID != -1)
itemRecentsSimImage.beVisibleIf(areMultipleSIMsAvailable && call.simID != -1)
itemRecentsSimId.beVisibleIf(areMultipleSIMsAvailable && call.simID != -1)
if (areMultipleSIMsAvailable && call.simID != -1) {
item_recents_sim_image.applyColorFilter(textColor)
item_recents_sim_id.setTextColor(textColor.getContrastColor())
item_recents_sim_id.text = call.simID.toString()
itemRecentsSimImage.applyColorFilter(textColor)
itemRecentsSimId.setTextColor(textColor.getContrastColor())
itemRecentsSimId.text = call.simID.toString()
}
SimpleContactsHelper(context).loadContactImage(call.photoUri, item_recents_image, call.name)
SimpleContactsHelper(root.context).loadContactImage(call.photoUri, itemRecentsImage, call.name)
val drawable = when (call.type) {
Calls.OUTGOING_TYPE -> outgoingCallIcon
@ -332,17 +343,15 @@ class RecentCallsAdapter(
else -> incomingCallIcon
}
item_recents_type.setImageDrawable(drawable)
itemRecentsType.setImageDrawable(drawable)
overflow_menu_icon.beVisibleIf(showOverflowMenu)
if (showOverflowMenu) {
overflow_menu_icon.drawable.apply {
mutate()
setTint(activity.getProperTextColor())
}
overflow_menu_icon.setOnClickListener {
showPopupMenu(overflow_menu_anchor, call)
}
overflowMenuIcon.beVisibleIf(showOverflowMenu)
overflowMenuIcon.drawable.apply {
mutate()
setTint(activity.getProperTextColor())
}
overflowMenuIcon.setOnClickListener {
showPopupMenu(overflowMenuAnchor, call)
}
}
}
@ -358,14 +367,19 @@ class RecentCallsAdapter(
inflate(R.menu.menu_recent_item_options)
menu.apply {
val areMultipleSIMsAvailable = activity.areMultipleSIMsAvailable()
findItem(R.id.cab_call).isVisible = !areMultipleSIMsAvailable
findItem(R.id.cab_call_sim_1).isVisible = areMultipleSIMsAvailable
findItem(R.id.cab_call_sim_2).isVisible = areMultipleSIMsAvailable
findItem(R.id.cab_view_details).isVisible = contact != null
findItem(R.id.cab_call).isVisible = !areMultipleSIMsAvailable && !call.isUnknownNumber
findItem(R.id.cab_call_sim_1).isVisible = areMultipleSIMsAvailable && !call.isUnknownNumber
findItem(R.id.cab_call_sim_2).isVisible = areMultipleSIMsAvailable && !call.isUnknownNumber
findItem(R.id.cab_send_sms).isVisible = !call.isUnknownNumber
findItem(R.id.cab_view_details).isVisible = contact != null && !call.isUnknownNumber
findItem(R.id.cab_add_number).isVisible = !call.isUnknownNumber
findItem(R.id.cab_copy_number).isVisible = !call.isUnknownNumber
findItem(R.id.cab_show_call_details).isVisible = !call.isUnknownNumber
findItem(R.id.cab_block_number).title = activity.addLockedLabelIfNeeded(R.string.block_number)
findItem(R.id.cab_block_number).isVisible = isNougatPlus()
findItem(R.id.cab_remove_default_sim).isVisible = activity.config.getCustomSIM(selectedNumber) != ""
findItem(R.id.cab_block_number).isVisible = isNougatPlus() && !call.isUnknownNumber
findItem(R.id.cab_remove_default_sim).isVisible = (activity.config.getCustomSIM(selectedNumber) ?: "") != "" && !call.isUnknownNumber
}
setOnMenuItemClickListener { item ->
val callId = call.id
when (item.itemId) {
@ -374,49 +388,59 @@ class RecentCallsAdapter(
callContact()
}
}
R.id.cab_call_sim_1 -> {
executeItemMenuOperation(callId) {
callContact(true)
}
}
R.id.cab_call_sim_2 -> {
executeItemMenuOperation(callId) {
callContact(false)
}
}
R.id.cab_send_sms -> {
executeItemMenuOperation(callId) {
sendSMS()
}
}
R.id.cab_view_details -> {
executeItemMenuOperation(callId) {
launchContactDetailsIntent(contact)
}
}
R.id.cab_add_number -> {
executeItemMenuOperation(callId) {
addNumberToContact()
}
}
R.id.cab_show_call_details -> {
executeItemMenuOperation(callId) {
showCallDetails()
}
}
R.id.cab_block_number -> {
selectedKeys.add(callId)
tryBlocking()
}
R.id.cab_remove -> {
selectedKeys.add(callId)
askConfirmRemove()
}
R.id.cab_copy_number -> {
executeItemMenuOperation(callId) {
copyNumber()
}
}
R.id.cab_remove_default_sim -> {
executeItemMenuOperation(callId) {
removeDefaultSIM()

View File

@ -1,19 +1,17 @@
package com.simplemobiletools.dialer.adapters
import android.view.Menu
import android.view.View
import android.view.ViewGroup
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.activities.SimpleActivity
import com.simplemobiletools.dialer.databinding.ItemSpeedDialBinding
import com.simplemobiletools.dialer.interfaces.RemoveSpeedDialListener
import com.simplemobiletools.dialer.models.SpeedDial
import kotlinx.android.synthetic.main.item_speed_dial.view.*
import java.util.*
class SpeedDialAdapter(
activity: SimpleActivity, var speedDialValues: ArrayList<SpeedDial>, private val removeListener: RemoveSpeedDialListener,
activity: SimpleActivity, var speedDialValues: List<SpeedDial>, private val removeListener: RemoveSpeedDialListener,
recyclerView: MyRecyclerView, itemClick: (Any) -> Unit
) : MyRecyclerViewAdapter(activity, recyclerView, itemClick) {
init {
@ -46,12 +44,15 @@ class SpeedDialAdapter(
override fun onActionModeDestroyed() {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_speed_dial, parent)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return createViewHolder(ItemSpeedDialBinding.inflate(layoutInflater, parent, false).root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val speedDial = speedDialValues[position]
holder.bindView(speedDial, true, true) { itemView, layoutPosition ->
setupView(itemView, speedDial)
val binding = ItemSpeedDialBinding.bind(itemView)
setupView(binding, speedDial)
}
bindViewHolder(holder)
}
@ -66,12 +67,12 @@ class SpeedDialAdapter(
finishActMode()
}
private fun setupView(view: View, speedDial: SpeedDial) {
view.apply {
private fun setupView(binding: ItemSpeedDialBinding, speedDial: SpeedDial) {
binding.apply {
var displayName = "${speedDial.id}. "
displayName += if (speedDial.isValid()) speedDial.displayName else ""
speed_dial_label.apply {
speedDialLabel.apply {
text = displayName
isSelected = selectedKeys.contains(speedDial.hashCode())
setTextColor(textColor)

View File

@ -19,7 +19,7 @@ class ViewPagerAdapter(val activity: SimpleActivity) : PagerAdapter() {
val view = activity.layoutInflater.inflate(layout, container, false)
container.addView(view)
(view as MyViewPagerFragment).apply {
(view as MyViewPagerFragment<*>).apply {
setupFragment(activity)
}

View File

@ -4,22 +4,24 @@ import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.beGoneIf
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.extensions.viewBinding
import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.databinding.DialogChangeSortingBinding
import com.simplemobiletools.dialer.extensions.config
import kotlinx.android.synthetic.main.dialog_change_sorting.view.*
class ChangeSortingDialog(val activity: BaseSimpleActivity, private val showCustomSorting: Boolean = false, private val callback: () -> Unit) {
private val binding by activity.viewBinding(DialogChangeSortingBinding::inflate)
private var currSorting = 0
private var config = activity.config
private var view = activity.layoutInflater.inflate(R.layout.dialog_change_sorting, null)
init {
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok) { dialog, which -> dialogConfirmed() }
.setNegativeButton(R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this, R.string.sort_by)
activity.setupDialogStuff(binding.root, this, R.string.sort_by)
}
currSorting = if (showCustomSorting && config.isCustomOrderSelected) {
@ -33,43 +35,41 @@ class ChangeSortingDialog(val activity: BaseSimpleActivity, private val showCust
}
private fun setupSortRadio() {
val sortingRadio = view.sorting_dialog_radio_sorting
binding.apply {
sortingDialogRadioSorting.setOnCheckedChangeListener { group, checkedId ->
val isCustomSorting = checkedId == sortingDialogRadioCustom.id
sortingDialogRadioOrder.beGoneIf(isCustomSorting)
divider.beGoneIf(isCustomSorting)
}
sortingRadio.setOnCheckedChangeListener { group, checkedId ->
val isCustomSorting = checkedId == sortingRadio.sorting_dialog_radio_custom.id
view.sorting_dialog_radio_order.beGoneIf(isCustomSorting)
view.divider.beGoneIf(isCustomSorting)
}
val sortBtn = when {
currSorting and SORT_BY_FIRST_NAME != 0 -> sortingDialogRadioFirstName
currSorting and SORT_BY_MIDDLE_NAME != 0 -> sortingDialogRadioMiddleName
currSorting and SORT_BY_SURNAME != 0 -> sortingDialogRadioSurname
currSorting and SORT_BY_FULL_NAME != 0 -> sortingDialogRadioFullName
currSorting and SORT_BY_CUSTOM != 0 -> sortingDialogRadioCustom
else -> sortingDialogRadioDateCreated
}
sortBtn.isChecked = true
val sortBtn = when {
currSorting and SORT_BY_FIRST_NAME != 0 -> sortingRadio.sorting_dialog_radio_first_name
currSorting and SORT_BY_MIDDLE_NAME != 0 -> sortingRadio.sorting_dialog_radio_middle_name
currSorting and SORT_BY_SURNAME != 0 -> sortingRadio.sorting_dialog_radio_surname
currSorting and SORT_BY_FULL_NAME != 0 -> sortingRadio.sorting_dialog_radio_full_name
currSorting and SORT_BY_CUSTOM != 0 -> sortingRadio.sorting_dialog_radio_custom
else -> sortingRadio.sorting_dialog_radio_date_created
if (showCustomSorting) {
sortingDialogRadioCustom.isChecked = config.isCustomOrderSelected
}
sortingDialogRadioCustom.beGoneIf(!showCustomSorting)
}
sortBtn.isChecked = true
if (showCustomSorting) {
sortingRadio.sorting_dialog_radio_custom.isChecked = config.isCustomOrderSelected
}
view.sorting_dialog_radio_custom.beGoneIf(!showCustomSorting)
}
private fun setupOrderRadio() {
val orderRadio = view.sorting_dialog_radio_order
var orderBtn = orderRadio.sorting_dialog_radio_ascending
var orderBtn = binding.sortingDialogRadioAscending
if (currSorting and SORT_DESCENDING != 0) {
orderBtn = orderRadio.sorting_dialog_radio_descending
orderBtn = binding.sortingDialogRadioDescending
}
orderBtn.isChecked = true
}
private fun dialogConfirmed() {
val sortingRadio = view.sorting_dialog_radio_sorting
var sorting = when (sortingRadio.checkedRadioButtonId) {
var sorting = when (binding.sortingDialogRadioSorting.checkedRadioButtonId) {
R.id.sorting_dialog_radio_first_name -> SORT_BY_FIRST_NAME
R.id.sorting_dialog_radio_middle_name -> SORT_BY_MIDDLE_NAME
R.id.sorting_dialog_radio_surname -> SORT_BY_SURNAME
@ -78,7 +78,7 @@ class ChangeSortingDialog(val activity: BaseSimpleActivity, private val showCust
else -> SORT_BY_DATE_CREATED
}
if (sorting != SORT_BY_CUSTOM && view.sorting_dialog_radio_order.checkedRadioButtonId == R.id.sorting_dialog_radio_descending) {
if (sorting != SORT_BY_CUSTOM && binding.sortingDialogRadioOrder.checkedRadioButtonId == R.id.sorting_dialog_radio_descending) {
sorting = sorting or SORT_DESCENDING
}

View File

@ -6,17 +6,17 @@ import androidx.fragment.app.FragmentManager
import com.simplemobiletools.commons.adapters.SimpleListItemAdapter
import com.simplemobiletools.commons.fragments.BaseBottomSheetDialogFragment
import com.simplemobiletools.commons.models.SimpleListItem
import com.simplemobiletools.dialer.R
import kotlinx.android.synthetic.main.layout_simple_recycler_view.*
import com.simplemobiletools.dialer.databinding.LayoutSimpleRecyclerViewBinding
// same as BottomSheetChooserDialog but with dynamic updates
class DynamicBottomSheetChooserDialog : BaseBottomSheetDialogFragment() {
private lateinit var binding: LayoutSimpleRecyclerViewBinding
var onItemClick: ((SimpleListItem) -> Unit)? = null
override fun setupContentView(parent: ViewGroup) {
val child = layoutInflater.inflate(R.layout.layout_simple_recycler_view, parent, false)
parent.addView(child)
binding = LayoutSimpleRecyclerViewBinding.inflate(layoutInflater, parent, false)
parent.addView(binding.root)
setupRecyclerView()
}
@ -27,13 +27,13 @@ class DynamicBottomSheetChooserDialog : BaseBottomSheetDialogFragment() {
}
private fun getRecyclerViewAdapter(): SimpleListItemAdapter {
var adapter = recycler_view.adapter as? SimpleListItemAdapter
var adapter = binding.recyclerView.adapter as? SimpleListItemAdapter
if (adapter == null) {
adapter = SimpleListItemAdapter(requireActivity()) {
onItemClick?.invoke(it)
dismissAllowingStateLoss()
}
recycler_view.adapter = adapter
binding.recyclerView.adapter = adapter
}
return adapter
}

View File

@ -0,0 +1,34 @@
package com.simplemobiletools.dialer.dialogs
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.activities.SimpleActivity
import com.simplemobiletools.dialer.databinding.DialogExportCallHistoryBinding
class ExportCallHistoryDialog(val activity: SimpleActivity, callback: (filename: String) -> Unit) {
init {
val binding = DialogExportCallHistoryBinding.inflate(activity.layoutInflater).apply {
exportCallHistoryFilename.setText("call_history_${activity.getCurrentFormattedDateTime()}")
}
activity.getAlertDialogBuilder().setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null).apply {
activity.setupDialogStuff(binding.root, this, R.string.export_call_history) { alertDialog ->
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
val filename = binding.exportCallHistoryFilename.value
when {
filename.isEmpty() -> activity.toast(R.string.empty_name)
filename.isAValidFilename() -> {
callback(filename)
alertDialog.dismiss()
}
else -> activity.toast(R.string.invalid_name)
}
}
}
}
}
}

View File

@ -1,37 +1,36 @@
package com.simplemobiletools.dialer.dialogs
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.getMyContactsCursor
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.helpers.SMT_PRIVATE
import com.simplemobiletools.commons.extensions.getVisibleContactSources
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ContactsHelper
import com.simplemobiletools.commons.helpers.MyContactsContentProvider
import com.simplemobiletools.commons.models.contacts.*
import com.simplemobiletools.commons.helpers.SMT_PRIVATE
import com.simplemobiletools.commons.models.contacts.Contact
import com.simplemobiletools.commons.models.contacts.ContactSource
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.activities.SimpleActivity
import com.simplemobiletools.dialer.adapters.FilterContactSourcesAdapter
import com.simplemobiletools.dialer.databinding.DialogFilterContactSourcesBinding
import com.simplemobiletools.dialer.extensions.config
import kotlinx.android.synthetic.main.dialog_filter_contact_sources.view.*
class FilterContactSourcesDialog(val activity: SimpleActivity, private val callback: () -> Unit) {
private val binding by activity.viewBinding(DialogFilterContactSourcesBinding::inflate)
private var dialog: AlertDialog? = null
private val view = activity.layoutInflater.inflate(R.layout.dialog_filter_contact_sources, null)
private var contactSources = ArrayList<ContactSource>()
private var contacts = ArrayList<Contact>()
private var isContactSourcesReady = false
private var isContactsReady = false
init {
val contactHelper = ContactsHelper(activity)
contactHelper.getContactSources { contactSources ->
val contactHelper = ContactsHelper(activity)
contactHelper.getContactSources { contactSources ->
contactSources.mapTo(this@FilterContactSourcesDialog.contactSources) { it.copy() }
isContactSourcesReady = true
processDataIfReady()
}
contactHelper.getContacts(getAll = true) {
contactHelper.getContacts(getAll = true, showOnlyContactsWithNumbers = true) {
it.mapTo(contacts) { contact -> contact.copy() }
val privateCursor = activity.getMyContactsCursor(false, true)
val privateContacts = MyContactsContentProvider.getContacts(activity, privateCursor)
@ -61,14 +60,14 @@ class FilterContactSourcesDialog(val activity: SimpleActivity, private val callb
activity.runOnUiThread {
val selectedSources = activity.getVisibleContactSources()
view.filter_contact_sources_list.adapter = FilterContactSourcesAdapter(activity, contactSourcesWithCount, selectedSources)
binding.filterContactSourcesList.adapter = FilterContactSourcesAdapter(activity, contactSourcesWithCount, selectedSources)
if (dialog == null) {
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok) { dialogInterface, i -> confirmContactSources() }
.setNegativeButton(R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this) { alertDialog ->
activity.setupDialogStuff(binding.root, this) { alertDialog ->
dialog = alertDialog
}
}
@ -77,7 +76,7 @@ class FilterContactSourcesDialog(val activity: SimpleActivity, private val callb
}
private fun confirmContactSources() {
val selectedContactSources = (view.filter_contact_sources_list.adapter as FilterContactSourcesAdapter).getSelectedContactSources()
val selectedContactSources = (binding.filterContactSourcesList.adapter as FilterContactSourcesAdapter).getSelectedContactSources()
val ignoredContactSources = contactSources.filter { !selectedContactSources.contains(it) }.map {
if (it.type == SMT_PRIVATE) SMT_PRIVATE else it.getFullIdentifier()
}.toHashSet()

View File

@ -3,16 +3,18 @@ package com.simplemobiletools.dialer.dialogs
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.extensions.viewBinding
import com.simplemobiletools.commons.helpers.TAB_CALL_HISTORY
import com.simplemobiletools.commons.helpers.TAB_CONTACTS
import com.simplemobiletools.commons.helpers.TAB_FAVORITES
import com.simplemobiletools.commons.views.MyAppCompatCheckbox
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.databinding.DialogManageVisibleTabsBinding
import com.simplemobiletools.dialer.extensions.config
import com.simplemobiletools.dialer.helpers.ALL_TABS_MASK
class ManageVisibleTabsDialog(val activity: BaseSimpleActivity) {
private var view = activity.layoutInflater.inflate(R.layout.dialog_manage_visible_tabs, null)
private val binding by activity.viewBinding(DialogManageVisibleTabsBinding::inflate)
private val tabs = LinkedHashMap<Int, Int>()
init {
@ -24,21 +26,21 @@ class ManageVisibleTabsDialog(val activity: BaseSimpleActivity) {
val showTabs = activity.config.showTabs
for ((key, value) in tabs) {
view.findViewById<MyAppCompatCheckbox>(value).isChecked = showTabs and key != 0
binding.root.findViewById<MyAppCompatCheckbox>(value).isChecked = showTabs and key != 0
}
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok) { dialog, which -> dialogConfirmed() }
.setNegativeButton(R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this)
activity.setupDialogStuff(binding.root, this)
}
}
private fun dialogConfirmed() {
var result = 0
for ((key, value) in tabs) {
if (view.findViewById<MyAppCompatCheckbox>(value).isChecked) {
if (binding.root.findViewById<MyAppCompatCheckbox>(value).isChecked) {
result += key
}
}

View File

@ -1,37 +1,36 @@
package com.simplemobiletools.dialer.dialogs
import android.graphics.Color
import android.view.KeyEvent
import android.view.inputmethod.EditorInfo
import android.widget.ImageView
import androidx.appcompat.app.AlertDialog
import com.reddit.indicatorfastscroll.FastScrollItemIndicator
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.models.contacts.Contact
import com.simplemobiletools.commons.views.MySearchMenu
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.activities.SimpleActivity
import com.simplemobiletools.dialer.adapters.ContactsAdapter
import kotlinx.android.synthetic.main.dialog_select_contact.view.*
import java.util.*
import com.simplemobiletools.dialer.databinding.DialogSelectContactBinding
import java.util.Locale
class SelectContactDialog(val activity: SimpleActivity, val contacts: List<Contact>, val callback: (selectedContact: Contact) -> Unit) {
private val binding by activity.viewBinding(DialogSelectContactBinding::inflate)
class SelectContactDialog(val activity: SimpleActivity, contacts: ArrayList<Contact>, val callback: (selectedContact: Contact) -> Unit) {
private var dialog: AlertDialog? = null
private var view = activity.layoutInflater.inflate(R.layout.dialog_select_contact, null)
init {
view.apply {
letter_fastscroller.textColor = context.getProperTextColor().getColorStateList()
letter_fastscroller_thumb.setupWithFastScroller(letter_fastscroller)
letter_fastscroller_thumb.textColor = context.getProperPrimaryColor().getContrastColor()
letter_fastscroller_thumb.thumbColor = context.getProperPrimaryColor().getColorStateList()
binding.apply {
letterFastscroller.textColor = activity.getProperTextColor().getColorStateList()
letterFastscrollerThumb.setupWithFastScroller(letterFastscroller)
letterFastscrollerThumb.textColor = activity.getProperPrimaryColor().getContrastColor()
letterFastscrollerThumb.thumbColor = activity.getProperPrimaryColor().getColorStateList()
letter_fastscroller.setupWithRecyclerView(select_contact_list, { position ->
try {
val name = contacts[position].getNameToDisplay()
val character = if (name.isNotEmpty()) name.substring(0, 1) else ""
FastScrollItemIndicator.Text(character.toUpperCase(Locale.getDefault()))
} catch (e: Exception) {
FastScrollItemIndicator.Text("")
}
})
setupLetterFastScroller(contacts)
configureSearchView()
select_contact_list.adapter = ContactsAdapter(activity, contacts, select_contact_list) {
selectContactList.adapter = ContactsAdapter(activity, contacts.toMutableList(), selectContactList, allowLongClick = false) {
callback(it as Contact)
dialog?.dismiss()
}
@ -39,10 +38,105 @@ class SelectContactDialog(val activity: SimpleActivity, contacts: ArrayList<Cont
activity.getAlertDialogBuilder()
.setNegativeButton(R.string.cancel, null)
.setOnKeyListener { _, i, keyEvent ->
if (keyEvent.action == KeyEvent.ACTION_UP && i == KeyEvent.KEYCODE_BACK) {
backPressed()
}
true
}
.apply {
activity.setupDialogStuff(view, this) { alertDialog ->
activity.setupDialogStuff(binding.root, this, R.string.choose_contact) { alertDialog ->
dialog = alertDialog
}
}
}
private fun setupLetterFastScroller(contacts: List<Contact>) {
binding.letterFastscroller.setupWithRecyclerView(binding.selectContactList, { position ->
try {
val name = contacts[position].getNameToDisplay()
val character = if (name.isNotEmpty()) name.substring(0, 1) else ""
FastScrollItemIndicator.Text(character.uppercase(Locale.getDefault()))
} catch (e: Exception) {
FastScrollItemIndicator.Text("")
}
})
}
private fun configureSearchView() = with(binding.contactSearchView) {
updateHintText(context.getString(R.string.search_contacts))
binding.topToolbarSearch.imeOptions = EditorInfo.IME_ACTION_DONE
toggleHideOnScroll(true)
setupMenu()
setSearchViewListeners()
updateSearchViewUi()
}
private fun MySearchMenu.updateSearchViewUi() {
getToolbar().beInvisible()
updateColors()
setBackgroundColor(Color.TRANSPARENT)
binding.topAppBarLayout.setBackgroundColor(Color.TRANSPARENT)
}
private fun MySearchMenu.setSearchViewListeners() {
onSearchOpenListener = {
updateSearchViewLeftIcon(R.drawable.ic_cross_vector)
}
onSearchClosedListener = {
binding.topToolbarSearch.clearFocus()
activity.hideKeyboard(binding.topToolbarSearch)
updateSearchViewLeftIcon(R.drawable.ic_search_vector)
}
onSearchTextChangedListener = { text ->
filterContactListBySearchQuery(text)
}
}
private fun updateSearchViewLeftIcon(iconResId: Int) = with(binding.root.findViewById<ImageView>(R.id.top_toolbar_search_icon)) {
post {
setImageResource(iconResId)
}
}
private fun filterContactListBySearchQuery(query: String) {
val adapter = binding.selectContactList.adapter as? ContactsAdapter
var contactsToShow = contacts
if (query.isNotEmpty()) {
contactsToShow = contacts.filter { it.name.contains(query, true) }
}
checkPlaceholderVisibility(contactsToShow)
if (adapter?.contacts != contactsToShow) {
adapter?.updateItems(contactsToShow)
setupLetterFastScroller(contactsToShow)
binding.selectContactList.apply {
post {
scrollToPosition(0)
}
}
}
}
private fun checkPlaceholderVisibility(contacts: List<Contact>) = with(binding) {
contactsEmptyPlaceholder.beVisibleIf(contacts.isEmpty())
if (contactSearchView.isSearchOpen) {
contactsEmptyPlaceholder.text = activity.getString(R.string.no_items_found)
}
letterFastscroller.beVisibleIf(contactsEmptyPlaceholder.isGone())
letterFastscrollerThumb.beVisibleIf(contactsEmptyPlaceholder.isGone())
}
private fun backPressed() {
if (binding.contactSearchView.isSearchOpen) {
binding.contactSearchView.closeSearch()
} else {
dialog?.dismiss()
}
}
}

View File

@ -9,10 +9,11 @@ import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.extensions.viewBinding
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.databinding.DialogSelectSimBinding
import com.simplemobiletools.dialer.extensions.config
import com.simplemobiletools.dialer.extensions.getAvailableSIMCardLabels
import kotlinx.android.synthetic.main.dialog_select_sim.view.*
@SuppressLint("MissingPermission")
class SelectSIMDialog(
@ -22,28 +23,25 @@ class SelectSIMDialog(
val callback: (handle: PhoneAccountHandle?) -> Unit
) {
private var dialog: AlertDialog? = null
private val view = activity.layoutInflater.inflate(R.layout.dialog_select_sim, null)
private val binding by activity.viewBinding(DialogSelectSimBinding::inflate)
init {
val radioGroup = view.select_sim_radio_group
view.apply {
select_sim_remember_holder.setOnClickListener {
select_sim_remember.toggle()
}
binding.selectSimRememberHolder.setOnClickListener {
binding.selectSimRemember.toggle()
}
activity.getAvailableSIMCardLabels().forEachIndexed { index, SIMAccount ->
val radioButton = (activity.layoutInflater.inflate(R.layout.radio_button, null) as RadioButton).apply {
text = "${index + 1} - ${SIMAccount.label}"
id = index
setOnClickListener { selectedSIM(SIMAccount.handle, SIMAccount.label) }
setOnClickListener { selectedSIM(SIMAccount.handle) }
}
radioGroup!!.addView(radioButton, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
binding.selectSimRadioGroup.addView(radioButton, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
}
activity.getAlertDialogBuilder()
.apply {
activity.setupDialogStuff(view, this) { alertDialog ->
activity.setupDialogStuff(binding.root, this) { alertDialog ->
dialog = alertDialog
}
}
@ -53,9 +51,9 @@ class SelectSIMDialog(
}
}
private fun selectedSIM(handle: PhoneAccountHandle, label: String) {
if (view.select_sim_remember.isChecked) {
activity.config.saveCustomSIM(phoneNumber, label)
private fun selectedSIM(handle: PhoneAccountHandle) {
if (binding.selectSimRemember.isChecked) {
activity.config.saveCustomSIM(phoneNumber, handle)
}
callback(handle)

View File

@ -4,33 +4,31 @@ import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.dialer.R
import com.simplemobiletools.commons.extensions.viewBinding
import com.simplemobiletools.dialer.activities.SimpleActivity
import com.simplemobiletools.dialer.adapters.RecentCallsAdapter
import com.simplemobiletools.dialer.databinding.DialogShowGroupedCallsBinding
import com.simplemobiletools.dialer.helpers.RecentsHelper
import com.simplemobiletools.dialer.models.RecentCall
import kotlinx.android.synthetic.main.dialog_show_grouped_calls.view.*
class ShowGroupedCallsDialog(val activity: BaseSimpleActivity, callIds: ArrayList<Int>) {
private var dialog: AlertDialog? = null
private var view = activity.layoutInflater.inflate(R.layout.dialog_show_grouped_calls, null)
private val binding by activity.viewBinding(DialogShowGroupedCallsBinding::inflate)
init {
view.apply {
RecentsHelper(activity).getRecentCalls(false) { allRecents ->
val recents = allRecents.filter { callIds.contains(it.id) }.toMutableList() as ArrayList<RecentCall>
activity.runOnUiThread {
RecentCallsAdapter(activity as SimpleActivity, recents, select_grouped_calls_list, null, false) {
}.apply {
select_grouped_calls_list.adapter = this
}
RecentsHelper(activity).getRecentCalls(false) { allRecents ->
val recents = allRecents.filter { callIds.contains(it.id) }.toMutableList() as ArrayList<RecentCall>
activity.runOnUiThread {
RecentCallsAdapter(activity as SimpleActivity, recents, binding.selectGroupedCallsList, null, false) {
}.apply {
binding.selectGroupedCallsList.adapter = this
}
}
}
activity.getAlertDialogBuilder()
.apply {
activity.setupDialogStuff(view, this) { alertDialog ->
activity.setupDialogStuff(binding.root, this) { alertDialog ->
dialog = alertDialog
}
}

View File

@ -76,12 +76,10 @@ fun SimpleActivity.getHandleToUse(intent: Intent?, phoneNumber: String, callback
val defaultHandle = telecomManager.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL)
when {
intent?.hasExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE) == true -> callback(intent.getParcelableExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE)!!)
config.getCustomSIM(phoneNumber)?.isNotEmpty() == true -> {
val storedLabel = Uri.decode(config.getCustomSIM(phoneNumber))
val availableSIMs = getAvailableSIMCardLabels()
val firstOrNull = availableSIMs.firstOrNull { it.label == storedLabel }?.handle ?: availableSIMs.first().handle
callback(firstOrNull)
config.getCustomSIM(phoneNumber) != null -> {
callback(config.getCustomSIM(phoneNumber))
}
defaultHandle != null -> callback(defaultHandle)
else -> {
SelectSIMDialog(this, phoneNumber, onDismiss = {

View File

@ -16,8 +16,8 @@ val Context.audioManager: AudioManager get() = getSystemService(Context.AUDIO_SE
val Context.powerManager: PowerManager get() = getSystemService(Context.POWER_SERVICE) as PowerManager
@SuppressLint("MissingPermission")
fun Context.getAvailableSIMCardLabels(): ArrayList<SIMAccount> {
val SIMAccounts = ArrayList<SIMAccount>()
fun Context.getAvailableSIMCardLabels(): List<SIMAccount> {
val SIMAccounts = mutableListOf<SIMAccount>()
try {
telecomManager.callCapablePhoneAccounts.forEachIndexed { index, account ->
val phoneAccount = telecomManager.getPhoneAccount(account)

View File

@ -0,0 +1,35 @@
package com.simplemobiletools.dialer.extensions
import android.content.SharedPreferences
import android.telecom.PhoneAccountHandle
import com.google.gson.Gson
import com.google.gson.JsonSyntaxException
import com.simplemobiletools.dialer.models.PhoneAccountHandleModel
fun SharedPreferences.Editor.putPhoneAccountHandle(
key: String,
parcelable: PhoneAccountHandle
): SharedPreferences.Editor {
val componentName = parcelable.componentName
val myPhoneAccountHandleModel = PhoneAccountHandleModel(
componentName.packageName, componentName.className, parcelable.id
)
val json = Gson().toJson(myPhoneAccountHandleModel)
return putString(key, json)
}
inline fun <reified T : PhoneAccountHandleModel?> SharedPreferences.getPhoneAccountHandleModel(
key: String,
default: T
): T {
val json = getString(key, null)
return try {
if (json != null) {
Gson().fromJson(json, T::class.java)
} else {
default
}
} catch (_: JsonSyntaxException) {
default
}
}

View File

@ -11,15 +11,24 @@ import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.activities.MainActivity
import com.simplemobiletools.dialer.activities.SimpleActivity
import com.simplemobiletools.dialer.adapters.ContactsAdapter
import com.simplemobiletools.dialer.databinding.FragmentContactsBinding
import com.simplemobiletools.dialer.databinding.FragmentLettersLayoutBinding
import com.simplemobiletools.dialer.extensions.launchCreateNewContactIntent
import com.simplemobiletools.dialer.extensions.startContactDetailsIntent
import com.simplemobiletools.dialer.interfaces.RefreshItemsListener
import kotlinx.android.synthetic.main.fragment_letters_layout.view.*
import java.util.*
import java.util.Locale
class ContactsFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet), RefreshItemsListener {
class ContactsFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment<MyViewPagerFragment.LettersInnerBinding>(context, attributeSet),
RefreshItemsListener {
private lateinit var binding: FragmentLettersLayoutBinding
private var allContacts = ArrayList<Contact>()
override fun onFinishInflate() {
super.onFinishInflate()
binding = FragmentLettersLayoutBinding.bind(FragmentContactsBinding.bind(this).contactsFragment)
innerBinding = LettersInnerBinding(binding)
}
override fun setupFragment() {
val placeholderResId = if (context.hasPermission(PERMISSION_READ_CONTACTS)) {
R.string.no_contacts_found
@ -27,7 +36,7 @@ class ContactsFragment(context: Context, attributeSet: AttributeSet) : MyViewPag
R.string.could_not_access_contacts
}
fragment_placeholder.text = context.getString(placeholderResId)
binding.fragmentPlaceholder.text = context.getString(placeholderResId)
val placeholderActionResId = if (context.hasPermission(PERMISSION_READ_CONTACTS)) {
R.string.create_new_contact
@ -35,7 +44,7 @@ class ContactsFragment(context: Context, attributeSet: AttributeSet) : MyViewPag
R.string.request_access
}
fragment_placeholder_2.apply {
binding.fragmentPlaceholder2.apply {
text = context.getString(placeholderActionResId)
underlineText()
setOnClickListener {
@ -49,20 +58,22 @@ class ContactsFragment(context: Context, attributeSet: AttributeSet) : MyViewPag
}
override fun setupColors(textColor: Int, primaryColor: Int, properPrimaryColor: Int) {
(fragment_list?.adapter as? MyRecyclerViewAdapter)?.updateTextColor(textColor)
fragment_placeholder.setTextColor(textColor)
fragment_placeholder_2.setTextColor(properPrimaryColor)
binding.apply {
(fragmentList?.adapter as? MyRecyclerViewAdapter)?.updateTextColor(textColor)
fragmentPlaceholder.setTextColor(textColor)
fragmentPlaceholder2.setTextColor(properPrimaryColor)
letter_fastscroller.textColor = textColor.getColorStateList()
letter_fastscroller.pressedTextColor = properPrimaryColor
letter_fastscroller_thumb.setupWithFastScroller(letter_fastscroller)
letter_fastscroller_thumb.textColor = properPrimaryColor.getContrastColor()
letter_fastscroller_thumb.thumbColor = properPrimaryColor.getColorStateList()
letterFastscroller.textColor = textColor.getColorStateList()
letterFastscroller.pressedTextColor = properPrimaryColor
letterFastscrollerThumb.setupWithFastScroller(letterFastscroller)
letterFastscrollerThumb.textColor = properPrimaryColor.getContrastColor()
letterFastscrollerThumb.thumbColor = properPrimaryColor.getColorStateList()
}
}
override fun refreshItems(callback: (() -> Unit)?) {
val privateCursor = context?.getMyContactsCursor(false, true)
ContactsHelper(context).getContacts { contacts ->
ContactsHelper(context).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
allContacts = contacts
if (SMT_PRIVATE !in context.baseConfig.ignoredContactSources) {
@ -82,40 +93,48 @@ class ContactsFragment(context: Context, attributeSet: AttributeSet) : MyViewPag
}
private fun gotContacts(contacts: ArrayList<Contact>) {
setupLetterFastscroller(contacts)
setupLetterFastScroller(contacts)
if (contacts.isEmpty()) {
fragment_placeholder.beVisible()
fragment_placeholder_2.beVisible()
fragment_list.beGone()
binding.apply {
fragmentPlaceholder.beVisible()
fragmentPlaceholder2.beVisible()
fragmentList.beGone()
}
} else {
fragment_placeholder.beGone()
fragment_placeholder_2.beGone()
fragment_list.beVisible()
binding.apply {
fragmentPlaceholder.beGone()
fragmentPlaceholder2.beGone()
fragmentList.beVisible()
}
val currAdapter = fragment_list.adapter
if (currAdapter == null) {
ContactsAdapter(activity as SimpleActivity, contacts, fragment_list, this) {
if (binding.fragmentList.adapter == null) {
ContactsAdapter(
activity = activity as SimpleActivity,
contacts = contacts,
recyclerView = binding.fragmentList,
refreshItemsListener = this
) {
val contact = it as Contact
activity?.startContactDetailsIntent(contact)
}.apply {
fragment_list.adapter = this
binding.fragmentList.adapter = this
}
if (context.areSystemAnimationsEnabled) {
fragment_list.scheduleLayoutAnimation()
binding.fragmentList.scheduleLayoutAnimation()
}
} else {
(currAdapter as ContactsAdapter).updateItems(contacts)
(binding.fragmentList.adapter as ContactsAdapter).updateItems(contacts)
}
}
}
private fun setupLetterFastscroller(contacts: ArrayList<Contact>) {
letter_fastscroller.setupWithRecyclerView(fragment_list, { position ->
private fun setupLetterFastScroller(contacts: ArrayList<Contact>) {
binding.letterFastscroller.setupWithRecyclerView(binding.fragmentList, { position ->
try {
val name = contacts[position].getNameToDisplay()
val character = if (name.isNotEmpty()) name.substring(0, 1) else ""
FastScrollItemIndicator.Text(character.toUpperCase(Locale.getDefault()).normalizeString())
FastScrollItemIndicator.Text(character.uppercase(Locale.getDefault()).normalizeString())
} catch (e: Exception) {
FastScrollItemIndicator.Text("")
}
@ -123,43 +142,44 @@ class ContactsFragment(context: Context, attributeSet: AttributeSet) : MyViewPag
}
override fun onSearchClosed() {
fragment_placeholder.beVisibleIf(allContacts.isEmpty())
(fragment_list.adapter as? ContactsAdapter)?.updateItems(allContacts)
setupLetterFastscroller(allContacts)
binding.fragmentPlaceholder.beVisibleIf(allContacts.isEmpty())
(binding.fragmentList.adapter as? ContactsAdapter)?.updateItems(allContacts)
setupLetterFastScroller(allContacts)
}
override fun onSearchQueryChanged(text: String) {
val shouldNormalize = text.normalizeString() == text
val filtered = allContacts.filter {
getProperText(it.getNameToDisplay(), shouldNormalize).contains(text, true) ||
getProperText(it.nickname, shouldNormalize).contains(text, true) ||
it.phoneNumbers.any {
text.normalizePhoneNumber().isNotEmpty() && it.normalizedNumber.contains(text.normalizePhoneNumber(), true)
} ||
it.emails.any { it.value.contains(text, true) } ||
it.addresses.any { getProperText(it.value, shouldNormalize).contains(text, true) } ||
it.IMs.any { it.value.contains(text, true) } ||
getProperText(it.notes, shouldNormalize).contains(text, true) ||
getProperText(it.organization.company, shouldNormalize).contains(text, true) ||
getProperText(it.organization.jobPosition, shouldNormalize).contains(text, true) ||
it.websites.any { it.contains(text, true) }
} as ArrayList
val shouldNormalize = text.normalizeString() == text
val filtered = allContacts.filter {
getProperText(it.getNameToDisplay(), shouldNormalize).contains(text, true) ||
getProperText(it.nickname, shouldNormalize).contains(text, true) ||
it.phoneNumbers.any {
text.normalizePhoneNumber().isNotEmpty() && it.normalizedNumber.contains(text.normalizePhoneNumber(), true)
} ||
it.emails.any { it.value.contains(text, true) } ||
it.addresses.any { getProperText(it.value, shouldNormalize).contains(text, true) } ||
it.IMs.any { it.value.contains(text, true) } ||
getProperText(it.notes, shouldNormalize).contains(text, true) ||
getProperText(it.organization.company, shouldNormalize).contains(text, true) ||
getProperText(it.organization.jobPosition, shouldNormalize).contains(text, true) ||
it.websites.any { it.contains(text, true) }
} as ArrayList
filtered.sortBy {
val nameToDisplay = it.getNameToDisplay()
!getProperText(nameToDisplay, shouldNormalize).startsWith(text, true) && !nameToDisplay.contains(text, true)
}
fragment_placeholder.beVisibleIf(filtered.isEmpty())
(fragment_list.adapter as? ContactsAdapter)?.updateItems(filtered, text)
setupLetterFastscroller(filtered)
filtered.sortBy {
val nameToDisplay = it.getNameToDisplay()
!getProperText(nameToDisplay, shouldNormalize).startsWith(text, true) && !nameToDisplay.contains(text, true)
}
binding.fragmentPlaceholder.beVisibleIf(filtered.isEmpty())
(binding.fragmentList.adapter as? ContactsAdapter)?.updateItems(filtered, text)
setupLetterFastScroller(filtered)
}
private fun requestReadContactsPermission() {
activity?.handlePermission(PERMISSION_READ_CONTACTS) {
if (it) {
fragment_placeholder.text = context.getString(R.string.no_contacts_found)
fragment_placeholder_2.text = context.getString(R.string.create_new_contact)
ContactsHelper(context).getContacts(false) { contacts ->
binding.fragmentPlaceholder.text = context.getString(R.string.no_contacts_found)
binding.fragmentPlaceholder2.text = context.getString(R.string.create_new_contact)
ContactsHelper(context).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
activity?.runOnUiThread {
gotContacts(contacts)
}

View File

@ -6,26 +6,32 @@ import com.google.gson.Gson
import com.reddit.indicatorfastscroll.FastScrollItemIndicator
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.dialogs.CallConfirmationDialog
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ContactsHelper
import com.simplemobiletools.commons.helpers.MyContactsContentProvider
import com.simplemobiletools.commons.helpers.PERMISSION_READ_CONTACTS
import com.simplemobiletools.commons.helpers.SMT_PRIVATE
import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.contacts.Contact
import com.simplemobiletools.commons.views.MyGridLayoutManager
import com.simplemobiletools.commons.views.MyLinearLayoutManager
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.activities.SimpleActivity
import com.simplemobiletools.dialer.adapters.ContactsAdapter
import com.simplemobiletools.dialer.databinding.FragmentFavoritesBinding
import com.simplemobiletools.dialer.databinding.FragmentLettersLayoutBinding
import com.simplemobiletools.dialer.extensions.config
import com.simplemobiletools.dialer.helpers.Converters
import com.simplemobiletools.dialer.interfaces.RefreshItemsListener
import kotlinx.android.synthetic.main.fragment_letters_layout.view.*
import java.util.*
import java.util.Locale
class FavoritesFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet), RefreshItemsListener {
class FavoritesFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment<MyViewPagerFragment.LettersInnerBinding>(context, attributeSet),
RefreshItemsListener {
private lateinit var binding: FragmentLettersLayoutBinding
private var allContacts = ArrayList<Contact>()
override fun onFinishInflate() {
super.onFinishInflate()
binding = FragmentLettersLayoutBinding.bind(FragmentFavoritesBinding.bind(this).favoritesFragment)
innerBinding = LettersInnerBinding(binding)
}
override fun setupFragment() {
val placeholderResId = if (context.hasPermission(PERMISSION_READ_CONTACTS)) {
R.string.no_contacts_found
@ -33,28 +39,32 @@ class FavoritesFragment(context: Context, attributeSet: AttributeSet) : MyViewPa
R.string.could_not_access_contacts
}
fragment_placeholder.text = context.getString(placeholderResId)
fragment_placeholder_2.beGone()
binding.fragmentPlaceholder.text = context.getString(placeholderResId)
binding.fragmentPlaceholder2.beGone()
}
override fun setupColors(textColor: Int, primaryColor: Int, properPrimaryColor: Int) {
fragment_placeholder.setTextColor(textColor)
(fragment_list?.adapter as? MyRecyclerViewAdapter)?.updateTextColor(textColor)
binding.apply {
fragmentPlaceholder.setTextColor(textColor)
(fragmentList.adapter as? MyRecyclerViewAdapter)?.updateTextColor(textColor)
letter_fastscroller.textColor = textColor.getColorStateList()
letter_fastscroller.pressedTextColor = properPrimaryColor
letter_fastscroller_thumb.setupWithFastScroller(letter_fastscroller)
letter_fastscroller_thumb.textColor = properPrimaryColor.getContrastColor()
letter_fastscroller_thumb.thumbColor = properPrimaryColor.getColorStateList()
letterFastscroller.textColor = textColor.getColorStateList()
letterFastscroller.pressedTextColor = properPrimaryColor
letterFastscrollerThumb.setupWithFastScroller(letterFastscroller)
letterFastscrollerThumb.textColor = properPrimaryColor.getContrastColor()
letterFastscrollerThumb.thumbColor = properPrimaryColor.getColorStateList()
}
}
override fun refreshItems(callback: (() -> Unit)?) {
val privateCursor = context?.getMyContactsCursor(true, true)
ContactsHelper(context).getContacts { contacts ->
ContactsHelper(context).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
allContacts = contacts
if (SMT_PRIVATE !in context.baseConfig.ignoredContactSources) {
val privateContacts = MyContactsContentProvider.getContacts(context, privateCursor)
val privateCursor = context?.getMyContactsCursor(true, true)
val privateContacts = MyContactsContentProvider.getContacts(context, privateCursor).map {
it.copy(starred = 1)
}
if (privateContacts.isNotEmpty()) {
allContacts.addAll(privateContacts)
allContacts.sort()
@ -76,53 +86,79 @@ class FavoritesFragment(context: Context, attributeSet: AttributeSet) : MyViewPa
}
private fun gotContacts(contacts: ArrayList<Contact>) {
setupLetterFastscroller(contacts)
if (contacts.isEmpty()) {
fragment_placeholder.beVisible()
fragment_list.beGone()
} else {
fragment_placeholder.beGone()
fragment_list.beVisible()
val currAdapter = fragment_list.adapter
if (currAdapter == null) {
ContactsAdapter(
activity = activity as SimpleActivity,
contacts = contacts,
recyclerView = fragment_list,
refreshItemsListener = this,
showDeleteButton = false,
enableDrag = true,
) {
if (context.config.showCallConfirmation) {
CallConfirmationDialog(activity as SimpleActivity, (it as Contact).getNameToDisplay()) {
callContact(it)
}
} else {
callContact(it as Contact)
}
}.apply {
fragment_list.adapter = this
onDragEndListener = {
val adapter = fragment_list?.adapter
if (adapter is ContactsAdapter) {
val items = adapter.contacts
saveCustomOrderToPrefs(items)
setupLetterFastscroller(items)
}
}
}
if (context.areSystemAnimationsEnabled) {
fragment_list.scheduleLayoutAnimation()
}
setupLetterFastScroller(contacts)
binding.apply {
if (contacts.isEmpty()) {
fragmentPlaceholder.beVisible()
fragmentList.beGone()
} else {
(currAdapter as ContactsAdapter).updateItems(contacts)
fragmentPlaceholder.beGone()
fragmentList.beVisible()
updateListAdapter()
}
}
}
private fun updateListAdapter() {
val viewType = context.config.viewType
setViewType(viewType)
val currAdapter = binding.fragmentList.adapter as ContactsAdapter?
if (currAdapter == null) {
ContactsAdapter(
activity = activity as SimpleActivity,
contacts = allContacts,
recyclerView = binding.fragmentList,
refreshItemsListener = this,
viewType = viewType,
showDeleteButton = false,
enableDrag = true,
) {
if (context.config.showCallConfirmation) {
CallConfirmationDialog(activity as SimpleActivity, (it as Contact).getNameToDisplay()) {
activity?.apply {
initiateCall(it) { launchCallIntent(it) }
}
}
} else {
activity?.apply {
initiateCall(it as Contact) { launchCallIntent(it) }
}
}
}.apply {
binding.fragmentList.adapter = this
onDragEndListener = {
val adapter = binding.fragmentList.adapter
if (adapter is ContactsAdapter) {
val items = adapter.contacts
saveCustomOrderToPrefs(items)
setupLetterFastScroller(items)
}
}
onSpanCountListener = { newSpanCount ->
context.config.contactsGridColumnCount = newSpanCount
}
}
if (context.areSystemAnimationsEnabled) {
binding.fragmentList.scheduleLayoutAnimation()
}
} else {
currAdapter.viewType = viewType
currAdapter.updateItems(allContacts)
}
}
fun columnCountChanged() {
(binding.fragmentList.layoutManager as MyGridLayoutManager).spanCount = context!!.config.contactsGridColumnCount
binding.fragmentList.adapter?.apply {
notifyItemRangeChanged(0, allContacts.size)
}
}
private fun sortByCustomOrder(favorites: List<Contact>): ArrayList<Contact> {
val favoritesOrder = activity!!.config.favoritesContactsOrder
@ -137,7 +173,7 @@ class FavoritesFragment(context: Context, attributeSet: AttributeSet) : MyViewPa
return ArrayList(sorted)
}
private fun saveCustomOrderToPrefs(items: ArrayList<Contact>) {
private fun saveCustomOrderToPrefs(items: List<Contact>) {
activity?.apply {
val orderIds = items.map { it.contactId }
val orderGsonString = Gson().toJson(orderIds)
@ -145,36 +181,12 @@ class FavoritesFragment(context: Context, attributeSet: AttributeSet) : MyViewPa
}
}
private fun callContact(simpleContact: Contact) {
val phoneNumbers = simpleContact.phoneNumbers
if (phoneNumbers.isEmpty()) {
return
} else if (phoneNumbers.size <= 1) {
activity?.launchCallIntent(phoneNumbers.first().normalizedNumber)
} else {
val primaryNumber = simpleContact.phoneNumbers.find { it.isPrimary }
if (primaryNumber != null) {
activity?.launchCallIntent(primaryNumber.value)
} else {
val items = ArrayList<RadioItem>()
phoneNumbers.forEachIndexed { index, phoneNumber ->
val type = context.getPhoneNumberTypeText(phoneNumber.type, phoneNumber.label)
items.add(RadioItem(index, "${phoneNumber.normalizedNumber} ($type)", phoneNumber.normalizedNumber))
}
RadioGroupDialog(activity!!, items) {
activity?.launchCallIntent(it as String)
}
}
}
}
private fun setupLetterFastscroller(contacts: ArrayList<Contact>) {
letter_fastscroller.setupWithRecyclerView(fragment_list, { position ->
private fun setupLetterFastScroller(contacts: List<Contact>) {
binding.letterFastscroller.setupWithRecyclerView(binding.fragmentList, { position ->
try {
val name = contacts[position].getNameToDisplay()
val character = if (name.isNotEmpty()) name.substring(0, 1) else ""
FastScrollItemIndicator.Text(character.toUpperCase(Locale.getDefault()).normalizeString())
FastScrollItemIndicator.Text(character.uppercase(Locale.getDefault()).normalizeString())
} catch (e: Exception) {
FastScrollItemIndicator.Text("")
}
@ -182,9 +194,9 @@ class FavoritesFragment(context: Context, attributeSet: AttributeSet) : MyViewPa
}
override fun onSearchClosed() {
fragment_placeholder.beVisibleIf(allContacts.isEmpty())
(fragment_list.adapter as? ContactsAdapter)?.updateItems(allContacts)
setupLetterFastscroller(allContacts)
binding.fragmentPlaceholder.beVisibleIf(allContacts.isEmpty())
(binding.fragmentList.adapter as? ContactsAdapter)?.updateItems(allContacts)
setupLetterFastScroller(allContacts)
}
override fun onSearchQueryChanged(text: String) {
@ -194,8 +206,21 @@ class FavoritesFragment(context: Context, attributeSet: AttributeSet) : MyViewPa
it.name.startsWith(text, true)
}.toMutableList() as ArrayList<Contact>
fragment_placeholder.beVisibleIf(contacts.isEmpty())
(fragment_list.adapter as? ContactsAdapter)?.updateItems(contacts, text)
setupLetterFastscroller(contacts)
binding.fragmentPlaceholder.beVisibleIf(contacts.isEmpty())
(binding.fragmentList.adapter as? ContactsAdapter)?.updateItems(contacts, text)
setupLetterFastScroller(contacts)
}
private fun setViewType(viewType: Int) {
val spanCount = context.config.contactsGridColumnCount
val layoutManager = if (viewType == VIEW_TYPE_GRID) {
binding.letterFastscroller.beGone()
MyGridLayoutManager(context, spanCount)
} else {
binding.letterFastscroller.beVisible()
MyLinearLayoutManager(context)
}
binding.fragmentList.layoutManager = layoutManager
}
}

View File

@ -6,19 +6,23 @@ import android.widget.RelativeLayout
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.extensions.getProperPrimaryColor
import com.simplemobiletools.commons.extensions.getProperTextColor
import com.simplemobiletools.commons.extensions.getTextSize
import com.simplemobiletools.commons.helpers.SORT_BY_FIRST_NAME
import com.simplemobiletools.commons.helpers.SORT_BY_SURNAME
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.dialer.activities.MainActivity
import com.simplemobiletools.dialer.activities.SimpleActivity
import com.simplemobiletools.dialer.adapters.ContactsAdapter
import com.simplemobiletools.dialer.adapters.RecentCallsAdapter
import com.simplemobiletools.dialer.databinding.FragmentLettersLayoutBinding
import com.simplemobiletools.dialer.databinding.FragmentRecentsBinding
import com.simplemobiletools.dialer.extensions.config
import com.simplemobiletools.dialer.helpers.Config
import kotlinx.android.synthetic.main.fragment_letters_layout.view.*
import kotlinx.android.synthetic.main.fragment_recents.view.*
abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet) : RelativeLayout(context, attributeSet) {
abstract class MyViewPagerFragment<BINDING : MyViewPagerFragment.InnerBinding>(context: Context, attributeSet: AttributeSet) :
RelativeLayout(context, attributeSet) {
protected var activity: SimpleActivity? = null
protected lateinit var innerBinding: BINDING
private lateinit var config: Config
fun setupFragment(activity: SimpleActivity) {
@ -33,7 +37,7 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
fun startNameWithSurnameChanged(startNameWithSurname: Boolean) {
if (this !is RecentsFragment) {
(fragment_list.adapter as? ContactsAdapter)?.apply {
(innerBinding.fragmentList?.adapter as? ContactsAdapter)?.apply {
config.sorting = if (startNameWithSurname) SORT_BY_SURNAME else SORT_BY_FIRST_NAME
(this@MyViewPagerFragment.activity!! as MainActivity).refreshFragments()
}
@ -41,8 +45,22 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
}
fun finishActMode() {
(fragment_list?.adapter as? MyRecyclerViewAdapter)?.finishActMode()
(recents_list?.adapter as? MyRecyclerViewAdapter)?.finishActMode()
(innerBinding.fragmentList?.adapter as? MyRecyclerViewAdapter)?.finishActMode()
(innerBinding.recentsList?.adapter as? MyRecyclerViewAdapter)?.finishActMode()
}
fun fontSizeChanged() {
if (this is RecentsFragment) {
(innerBinding.recentsList?.adapter as? RecentCallsAdapter)?.apply {
fontSize = activity.getTextSize()
notifyDataSetChanged()
}
} else {
(innerBinding.fragmentList?.adapter as? ContactsAdapter)?.apply {
fontSize = activity.getTextSize()
notifyDataSetChanged()
}
}
}
abstract fun setupFragment()
@ -52,4 +70,19 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
abstract fun onSearchClosed()
abstract fun onSearchQueryChanged(text: String)
interface InnerBinding {
val fragmentList: MyRecyclerView?
val recentsList: MyRecyclerView?
}
class LettersInnerBinding(val binding: FragmentLettersLayoutBinding) : InnerBinding {
override val fragmentList: MyRecyclerView = binding.fragmentList
override val recentsList = null
}
class RecentsInnerBinding(val binding: FragmentRecentsBinding) : InnerBinding {
override val fragmentList = null
override val recentsList = binding.recentsList
}
}

View File

@ -8,17 +8,29 @@ import com.simplemobiletools.commons.helpers.ContactsHelper
import com.simplemobiletools.commons.helpers.MyContactsContentProvider
import com.simplemobiletools.commons.helpers.PERMISSION_READ_CALL_LOG
import com.simplemobiletools.commons.helpers.SMT_PRIVATE
import com.simplemobiletools.commons.models.contacts.Contact
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.activities.SimpleActivity
import com.simplemobiletools.dialer.adapters.RecentCallsAdapter
import com.simplemobiletools.dialer.databinding.FragmentRecentsBinding
import com.simplemobiletools.dialer.extensions.config
import com.simplemobiletools.dialer.helpers.MIN_RECENTS_THRESHOLD
import com.simplemobiletools.dialer.helpers.RecentsHelper
import com.simplemobiletools.dialer.interfaces.RefreshItemsListener
import com.simplemobiletools.dialer.models.RecentCall
import kotlinx.android.synthetic.main.fragment_recents.view.*
class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet), RefreshItemsListener {
private var allRecentCalls = ArrayList<RecentCall>()
class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment<MyViewPagerFragment.RecentsInnerBinding>(context, attributeSet),
RefreshItemsListener {
private lateinit var binding: FragmentRecentsBinding
private var allRecentCalls = listOf<RecentCall>()
private var recentsAdapter: RecentCallsAdapter? = null
override fun onFinishInflate() {
super.onFinishInflate()
binding = FragmentRecentsBinding.bind(this)
innerBinding = RecentsInnerBinding(binding)
}
override fun setupFragment() {
val placeholderResId = if (context.hasPermission(PERMISSION_READ_CALL_LOG)) {
@ -27,8 +39,8 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
R.string.could_not_access_the_call_history
}
recents_placeholder.text = context.getString(placeholderResId)
recents_placeholder_2.apply {
binding.recentsPlaceholder.text = context.getString(placeholderResId)
binding.recentsPlaceholder2.apply {
underlineText()
setOnClickListener {
requestCallLogPermission()
@ -37,10 +49,10 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
}
override fun setupColors(textColor: Int, primaryColor: Int, properPrimaryColor: Int) {
recents_placeholder.setTextColor(textColor)
recents_placeholder_2.setTextColor(properPrimaryColor)
binding.recentsPlaceholder.setTextColor(textColor)
binding.recentsPlaceholder2.setTextColor(properPrimaryColor)
(recents_list?.adapter as? RecentCallsAdapter)?.apply {
recentsAdapter?.apply {
initDrawables()
updateTextColor(textColor)
}
@ -49,36 +61,14 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
override fun refreshItems(callback: (() -> Unit)?) {
val privateCursor = context?.getMyContactsCursor(false, true)
val groupSubsequentCalls = context?.config?.groupSubsequentCalls ?: false
RecentsHelper(context).getRecentCalls(groupSubsequentCalls) { recents ->
ContactsHelper(context).getContacts { contacts ->
val querySize = allRecentCalls.size.coerceAtLeast(MIN_RECENTS_THRESHOLD)
RecentsHelper(context).getRecentCalls(groupSubsequentCalls, querySize) { recents ->
ContactsHelper(context).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
val privateContacts = MyContactsContentProvider.getContacts(context, privateCursor)
recents.filter { it.phoneNumber == it.name }.forEach { recent ->
var wasNameFilled = false
if (privateContacts.isNotEmpty()) {
val privateContact = privateContacts.firstOrNull { it.doesContainPhoneNumber(recent.phoneNumber) }
if (privateContact != null) {
recent.name = privateContact.getNameToDisplay()
wasNameFilled = true
}
}
if (!wasNameFilled) {
val contact = contacts.filter { it.phoneNumbers.isNotEmpty() }.firstOrNull { it.phoneNumbers.first().normalizedNumber == recent.phoneNumber }
if (contact != null) {
recent.name = contact.getNameToDisplay()
}
}
}
allRecentCalls = recents
// hide private contacts from recent calls
if (SMT_PRIVATE in context.baseConfig.ignoredContactSources) {
allRecentCalls = recents.filterNot { recent ->
val privateNumbers = privateContacts.flatMap { it.phoneNumbers }.map { it.value }
recent.phoneNumber in privateNumbers
} as ArrayList
}
.setNamesIfEmpty(contacts, privateContacts)
.hidePrivateContacts(privateContacts, SMT_PRIVATE in context.baseConfig.ignoredContactSources)
activity?.runOnUiThread {
gotRecents(allRecentCalls)
@ -87,19 +77,22 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
}
}
private fun gotRecents(recents: ArrayList<RecentCall>) {
private fun gotRecents(recents: List<RecentCall>) {
if (recents.isEmpty()) {
recents_placeholder.beVisible()
recents_placeholder_2.beGoneIf(context.hasPermission(PERMISSION_READ_CALL_LOG))
recents_list.beGone()
binding.apply {
recentsPlaceholder.beVisible()
recentsPlaceholder2.beGoneIf(context.hasPermission(PERMISSION_READ_CALL_LOG))
recentsList.beGone()
}
} else {
recents_placeholder.beGone()
recents_placeholder_2.beGone()
recents_list.beVisible()
binding.apply {
recentsPlaceholder.beGone()
recentsPlaceholder2.beGone()
recentsList.beVisible()
}
val currAdapter = recents_list.adapter
if (currAdapter == null) {
RecentCallsAdapter(activity as SimpleActivity, recents, recents_list, this, true) {
if (binding.recentsList.adapter == null) {
recentsAdapter = RecentCallsAdapter(activity as SimpleActivity, recents.toMutableList(), binding.recentsList, this, true) {
val recentCall = it as RecentCall
if (context.config.showCallConfirmation) {
CallConfirmationDialog(activity as SimpleActivity, recentCall.name) {
@ -108,15 +101,43 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
} else {
activity?.launchCallIntent(recentCall.phoneNumber)
}
}.apply {
recents_list.adapter = this
}
binding.recentsList.adapter = recentsAdapter
if (context.areSystemAnimationsEnabled) {
recents_list.scheduleLayoutAnimation()
binding.recentsList.scheduleLayoutAnimation()
}
binding.recentsList.endlessScrollListener = object : MyRecyclerView.EndlessScrollListener {
override fun updateTop() {}
override fun updateBottom() {
getMoreRecentCalls()
}
}
} else {
(currAdapter as RecentCallsAdapter).updateItems(recents)
recentsAdapter?.updateItems(recents)
}
}
}
private fun getMoreRecentCalls() {
val privateCursor = context?.getMyContactsCursor(false, true)
val groupSubsequentCalls = context?.config?.groupSubsequentCalls ?: false
val querySize = allRecentCalls.size.plus(MIN_RECENTS_THRESHOLD)
RecentsHelper(context).getRecentCalls(groupSubsequentCalls, querySize) { recents ->
ContactsHelper(context).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
val privateContacts = MyContactsContentProvider.getContacts(context, privateCursor)
allRecentCalls = recents
.setNamesIfEmpty(contacts, privateContacts)
.hidePrivateContacts(privateContacts, SMT_PRIVATE in context.baseConfig.ignoredContactSources)
activity?.runOnUiThread {
gotRecents(allRecentCalls)
}
}
}
}
@ -124,8 +145,8 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
private fun requestCallLogPermission() {
activity?.handlePermission(PERMISSION_READ_CALL_LOG) {
if (it) {
recents_placeholder.text = context.getString(R.string.no_previous_calls)
recents_placeholder_2.beGone()
binding.recentsPlaceholder.text = context.getString(R.string.no_previous_calls)
binding.recentsPlaceholder2.beGone()
val groupSubsequentCalls = context?.config?.groupSubsequentCalls ?: false
RecentsHelper(context).getRecentCalls(groupSubsequentCalls) { recents ->
@ -138,8 +159,8 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
}
override fun onSearchClosed() {
recents_placeholder.beVisibleIf(allRecentCalls.isEmpty())
(recents_list.adapter as? RecentCallsAdapter)?.updateItems(allRecentCalls)
binding.recentsPlaceholder.beVisibleIf(allRecentCalls.isEmpty())
recentsAdapter?.updateItems(allRecentCalls)
}
override fun onSearchQueryChanged(text: String) {
@ -149,7 +170,37 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
it.name.startsWith(text, true)
}.toMutableList() as ArrayList<RecentCall>
recents_placeholder.beVisibleIf(recentCalls.isEmpty())
(recents_list.adapter as? RecentCallsAdapter)?.updateItems(recentCalls, text)
binding.recentsPlaceholder.beVisibleIf(recentCalls.isEmpty())
recentsAdapter?.updateItems(recentCalls, text)
}
}
// hide private contacts from recent calls
private fun List<RecentCall>.hidePrivateContacts(privateContacts: List<Contact>, shouldHide: Boolean): List<RecentCall> {
return if (shouldHide) {
filterNot { recent ->
val privateNumbers = privateContacts.flatMap { it.phoneNumbers }.map { it.value }
recent.phoneNumber in privateNumbers
}
} else {
this
}
}
private fun List<RecentCall>.setNamesIfEmpty(contacts: List<Contact>, privateContacts: List<Contact>): ArrayList<RecentCall> {
val contactsWithNumbers = contacts.filter { it.phoneNumbers.isNotEmpty() }
return map { recent ->
if (recent.phoneNumber == recent.name) {
val privateContact = privateContacts.firstOrNull { it.doesContainPhoneNumber(recent.phoneNumber) }
val contact = contactsWithNumbers.firstOrNull { it.phoneNumbers.first().normalizedNumber == recent.phoneNumber }
when {
privateContact != null -> recent.copy(name = privateContact.getNameToDisplay())
contact != null -> recent.copy(name = contact.getNameToDisplay())
else -> recent
}
} else {
recent
}
} as ArrayList
}

View File

@ -35,7 +35,7 @@ fun getCallContact(context: Context, call: Call?, callback: (CallContact) -> Uni
val uri = Uri.decode(handle)
if (uri.startsWith("tel:")) {
val number = uri.substringAfter("tel:")
ContactsHelper(context).getContacts{ contacts ->
ContactsHelper(context).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
val privateContacts = MyContactsContentProvider.getContacts(context, privateCursor)
if (privateContacts.isNotEmpty()) {
contacts.addAll(privateContacts)

View File

@ -1,13 +1,11 @@
package com.simplemobiletools.dialer.helpers
import android.annotation.SuppressLint
import android.content.Context
import android.os.Handler
import android.telecom.Call
import android.telecom.CallAudioState
import android.telecom.InCallService
import android.telecom.VideoProfile
import com.simplemobiletools.dialer.extensions.config
import com.simplemobiletools.dialer.extensions.getStateCompat
import com.simplemobiletools.dialer.extensions.hasCapability
import com.simplemobiletools.dialer.extensions.isConference
@ -202,13 +200,11 @@ class CallManager {
fun getState() = getPrimaryCall()?.getStateCompat()
fun keypad(context: Context, char: Char) {
if (context.config.dialpadBeeps) {
fun keypad(char: Char) {
call?.playDtmfTone(char)
Handler().postDelayed({
call?.stopDtmfTone()
}, DIALPAD_TONE_LENGTH_MS)
}
}
}
}

View File

@ -85,7 +85,7 @@ class CallNotificationManager(private val context: Context) {
val builder = NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.drawable.ic_phone_vector)
.setContentIntent(openAppPendingIntent)
.setPriority(if (isHighPriority) NotificationCompat.PRIORITY_MAX else NotificationCompat.PRIORITY_DEFAULT)
.setPriority(if (isHighPriority) NotificationManager.IMPORTANCE_HIGH else NotificationCompat.PRIORITY_DEFAULT)
.setCategory(Notification.CATEGORY_CALL)
.setCustomContentView(collapsedView)
.setOngoing(true)

View File

@ -1,16 +1,20 @@
package com.simplemobiletools.dialer.helpers
import android.content.ComponentName
import android.content.Context
import android.net.Uri
import android.telecom.PhoneAccountHandle
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.simplemobiletools.commons.helpers.BaseConfig
import com.simplemobiletools.dialer.extensions.getPhoneAccountHandleModel
import com.simplemobiletools.dialer.extensions.putPhoneAccountHandle
import com.simplemobiletools.dialer.models.SpeedDial
class Config(context: Context) : BaseConfig(context) {
companion object {
fun newInstance(context: Context) = Config(context)
}
fun getSpeedDialValues(): ArrayList<SpeedDial> {
val speedDialType = object : TypeToken<List<SpeedDial>>() {}.type
val speedDialValues = Gson().fromJson<ArrayList<SpeedDial>>(speedDial, speedDialType) ?: ArrayList(1)
@ -25,15 +29,27 @@ class Config(context: Context) : BaseConfig(context) {
return speedDialValues
}
fun saveCustomSIM(number: String, SIMlabel: String) {
prefs.edit().putString(REMEMBER_SIM_PREFIX + number, Uri.encode(SIMlabel)).apply()
fun saveCustomSIM(number: String, handle: PhoneAccountHandle) {
prefs.edit().putPhoneAccountHandle(REMEMBER_SIM_PREFIX + number, handle).apply()
}
fun getCustomSIM(number: String) = prefs.getString(REMEMBER_SIM_PREFIX + number, "")
fun getCustomSIM(number: String): PhoneAccountHandle? {
val myPhoneAccountHandle = prefs.getPhoneAccountHandleModel(REMEMBER_SIM_PREFIX + number, null)
return if (myPhoneAccountHandle != null) {
val packageName = myPhoneAccountHandle.packageName
val className = myPhoneAccountHandle.className
val componentName = ComponentName(packageName, className)
val id = myPhoneAccountHandle.id
PhoneAccountHandle(componentName, id)
} else {
null
}
}
fun removeCustomSIM(number: String) {
prefs.edit().remove(REMEMBER_SIM_PREFIX + number).apply()
}
var showTabs: Int
get() = prefs.getInt(SHOW_TABS, ALL_TABS_MASK)
set(showTabs) = prefs.edit().putInt(SHOW_TABS, showTabs).apply()

View File

@ -19,6 +19,7 @@ const val DIALPAD_VIBRATION = "dialpad_vibration"
const val DIALPAD_BEEPS = "dialpad_beeps"
const val HIDE_DIALPAD_NUMBERS = "hide_dialpad_numbers"
const val ALWAYS_SHOW_FULLSCREEN = "always_show_fullscreen"
const val ALL_TABS_MASK = TAB_CONTACTS or TAB_FAVORITES or TAB_CALL_HISTORY
val tabsList = arrayListOf(TAB_CONTACTS, TAB_FAVORITES, TAB_CALL_HISTORY)
@ -28,3 +29,5 @@ const val ACCEPT_CALL = PATH + "accept_call"
const val DECLINE_CALL = PATH + "decline_call"
const val DIALPAD_TONE_LENGTH_MS = 150L // The length of DTMF tones in milliseconds
const val MIN_RECENTS_THRESHOLD = 30

View File

@ -1,6 +1,7 @@
package com.simplemobiletools.dialer.helpers
import android.annotation.SuppressLint
import android.content.ContentValues
import android.content.Context
import android.provider.CallLog.Calls
import com.simplemobiletools.commons.extensions.*
@ -13,10 +14,10 @@ import com.simplemobiletools.dialer.models.RecentCall
class RecentsHelper(private val context: Context) {
private val COMPARABLE_PHONE_NUMBER_LENGTH = 9
private val QUERY_LIMIT = "200"
private val QUERY_LIMIT = 200
private val contentUri = Calls.CONTENT_URI
@SuppressLint("MissingPermission")
fun getRecentCalls(groupSubsequentCalls: Boolean, callback: (ArrayList<RecentCall>) -> Unit) {
fun getRecentCalls(groupSubsequentCalls: Boolean, maxSize: Int = QUERY_LIMIT, callback: (List<RecentCall>) -> Unit) {
val privateCursor = context.getMyContactsCursor(false, true)
ensureBackgroundThread {
if (!context.hasPermission(PERMISSION_READ_CALL_LOG)) {
@ -24,27 +25,26 @@ class RecentsHelper(private val context: Context) {
return@ensureBackgroundThread
}
ContactsHelper(context).getContacts(false) { contacts ->
ContactsHelper(context).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
val privateContacts = MyContactsContentProvider.getContacts(context, privateCursor)
if (privateContacts.isNotEmpty()) {
contacts.addAll(privateContacts)
}
getRecents(contacts, groupSubsequentCalls, callback)
getRecents(contacts, groupSubsequentCalls, maxSize, callback = callback)
}
}
}
@SuppressLint("NewApi")
private fun getRecents(contacts: ArrayList<Contact>, groupSubsequentCalls: Boolean, callback: (ArrayList<RecentCall>) -> Unit) {
private fun getRecents(contacts: List<Contact>, groupSubsequentCalls: Boolean, maxSize: Int, callback: (List<RecentCall>) -> Unit) {
var recentCalls = ArrayList<RecentCall>()
val recentCalls = mutableListOf<RecentCall>()
var previousRecentCallFrom = ""
var previousStartTS = 0
val contactsNumbersMap = HashMap<String, String>()
val contactPhotosMap = HashMap<String, String>()
val uri = Calls.CONTENT_URI
val projection = arrayOf(
Calls._ID,
Calls.NUMBER,
@ -63,14 +63,14 @@ class RecentsHelper(private val context: Context) {
val cursor = if (isNougatPlus()) {
// https://issuetracker.google.com/issues/175198972?pli=1#comment6
val limitedUri = uri.buildUpon()
.appendQueryParameter(Calls.LIMIT_PARAM_KEY, QUERY_LIMIT)
val limitedUri = contentUri.buildUpon()
.appendQueryParameter(Calls.LIMIT_PARAM_KEY, QUERY_LIMIT.toString())
.build()
val sortOrder = "${Calls._ID} DESC"
val sortOrder = "${Calls.DATE} DESC"
context.contentResolver.query(limitedUri, projection, null, null, sortOrder)
} else {
val sortOrder = "${Calls._ID} DESC LIMIT $QUERY_LIMIT"
context.contentResolver.query(uri, projection, null, null, sortOrder)
val sortOrder = "${Calls.DATE} DESC LIMIT $QUERY_LIMIT"
context.contentResolver.query(contentUri, projection, null, null, sortOrder)
}
val contactsWithMultipleNumbers = contacts.filter { it.phoneNumbers.size > 1 }
@ -82,16 +82,25 @@ class RecentsHelper(private val context: Context) {
}
}
if (cursor?.moveToFirst() == true) {
cursor?.use {
if (!cursor.moveToFirst()) {
return@use
}
do {
val id = cursor.getIntValue(Calls._ID)
val number = cursor.getStringValue(Calls.NUMBER) ?: continue
var name = cursor.getStringValue(Calls.CACHED_NAME)
if (name == null || name.isEmpty()) {
name = number
var isUnknownNumber = false
val number = cursor.getStringValueOrNull(Calls.NUMBER)
if (number == null || number == "-1") {
isUnknownNumber = true
}
if (name == number) {
var name = cursor.getStringValueOrNull(Calls.CACHED_NAME)
if (name.isNullOrEmpty() || name == "-1") {
name = number.orEmpty()
}
if (name == number && !isUnknownNumber) {
if (contactsNumbersMap.containsKey(number)) {
name = contactsNumbersMap[number]!!
} else {
@ -100,7 +109,10 @@ class RecentsHelper(private val context: Context) {
name = contacts.filter { it.phoneNumbers.isNotEmpty() }.firstOrNull { contact ->
val curNumber = contact.phoneNumbers.first().normalizedNumber
if (curNumber.length >= COMPARABLE_PHONE_NUMBER_LENGTH) {
if (curNumber.substring(curNumber.length - COMPARABLE_PHONE_NUMBER_LENGTH) == normalizedNumber.substring(normalizedNumber.length - COMPARABLE_PHONE_NUMBER_LENGTH)) {
if (curNumber.substring(curNumber.length - COMPARABLE_PHONE_NUMBER_LENGTH) == normalizedNumber.substring(
normalizedNumber.length - COMPARABLE_PHONE_NUMBER_LENGTH
)
) {
contactsNumbersMap[number] = contact.getNameToDisplay()
return@firstOrNull true
}
@ -111,12 +123,12 @@ class RecentsHelper(private val context: Context) {
}
}
if (name.isEmpty()) {
if (name.isEmpty() || name == "-1") {
name = context.getString(R.string.unknown)
}
var photoUri = cursor.getStringValue(Calls.CACHED_PHOTO_URI) ?: ""
if (photoUri.isEmpty()) {
if (photoUri.isEmpty() && !number.isNullOrEmpty()) {
if (contactPhotosMap.containsKey(number)) {
photoUri = contactPhotosMap[number]!!
} else {
@ -139,7 +151,7 @@ class RecentsHelper(private val context: Context) {
val type = cursor.getIntValue(Calls.TYPE)
val accountId = cursor.getStringValue(Calls.PHONE_ACCOUNT_ID)
val simID = accountIdToSimIDMap[accountId] ?: -1
val neighbourIDs = ArrayList<Int>()
val neighbourIDs = mutableListOf<Int>()
var specificNumber = ""
var specificType = ""
@ -153,7 +165,20 @@ class RecentsHelper(private val context: Context) {
}
}
val recentCall = RecentCall(id, number, name, photoUri, startTS, duration, type, neighbourIDs, simID, specificNumber, specificType)
val recentCall = RecentCall(
id = id,
phoneNumber = number.orEmpty(),
name = name,
photoUri = photoUri,
startTS = startTS,
duration = duration,
type = type,
neighbourIDs = neighbourIDs,
simID = simID,
specificNumber = specificNumber,
specificType = specificType,
isUnknownNumber = isUnknownNumber
)
// if we have multiple missed calls from the same number, show it just once
if (!groupSubsequentCalls || "$number$name$simID" != previousRecentCallFrom) {
@ -163,23 +188,23 @@ class RecentsHelper(private val context: Context) {
}
previousRecentCallFrom = "$number$name$simID"
} while (cursor.moveToNext())
} while (cursor.moveToNext() && recentCalls.size < maxSize)
}
cursor?.close()
val blockedNumbers = context.getBlockedNumbers()
recentCalls = recentCalls.filter { !context.isNumberBlocked(it.phoneNumber, blockedNumbers) }.toMutableList() as ArrayList<RecentCall>
callback(recentCalls)
val recentResult = recentCalls
.filter { !context.isNumberBlocked(it.phoneNumber, blockedNumbers) }
callback(recentResult)
}
@SuppressLint("MissingPermission")
fun removeRecentCalls(ids: ArrayList<Int>, callback: () -> Unit) {
fun removeRecentCalls(ids: List<Int>, callback: () -> Unit) {
ensureBackgroundThread {
val uri = Calls.CONTENT_URI
ids.chunked(30).forEach { chunk ->
val selection = "${Calls._ID} IN (${getQuestionMarks(chunk.size)})"
val selectionArgs = chunk.map { it.toString() }.toTypedArray()
context.contentResolver.delete(uri, selection, selectionArgs)
context.contentResolver.delete(contentUri, selection, selectionArgs)
}
callback()
}
@ -190,8 +215,30 @@ class RecentsHelper(private val context: Context) {
activity.handlePermission(PERMISSION_WRITE_CALL_LOG) {
if (it) {
ensureBackgroundThread {
val uri = Calls.CONTENT_URI
context.contentResolver.delete(uri, null, null)
context.contentResolver.delete(contentUri, null, null)
callback()
}
}
}
}
fun restoreRecentCalls(activity: SimpleActivity, objects: List<RecentCall>, callback: () -> Unit) {
activity.handlePermission(PERMISSION_WRITE_CALL_LOG) {
if (it) {
ensureBackgroundThread {
val values = objects
.sortedBy { it.startTS }
.map {
ContentValues().apply {
put(Calls.NUMBER, it.phoneNumber)
put(Calls.TYPE, it.type)
put(Calls.DATE, it.startTS.toLong() * 1000L)
put(Calls.DURATION, it.duration)
put(Calls.CACHED_NAME, it.name)
}
}.toTypedArray()
context.contentResolver.bulkInsert(contentUri, values)
callback()
}
}

View File

@ -0,0 +1,7 @@
package com.simplemobiletools.dialer.models
data class PhoneAccountHandleModel(
val packageName: String,
val className: String,
val id: String
)

View File

@ -3,10 +3,24 @@ package com.simplemobiletools.dialer.models
import android.telephony.PhoneNumberUtils
import com.simplemobiletools.commons.extensions.normalizePhoneNumber
// model used at displaying recent calls, for contacts with multiple numbers specifify the number and type
/**
* Used at displaying recent calls.
* For contacts with multiple numbers specify the number and type
*/
@kotlinx.serialization.Serializable
data class RecentCall(
var id: Int, var phoneNumber: String, var name: String, var photoUri: String, var startTS: Int, var duration: Int, var type: Int,
var neighbourIDs: ArrayList<Int>, val simID: Int, var specificNumber: String, var specificType: String
val id: Int,
val phoneNumber: String,
val name: String,
val photoUri: String,
val startTS: Int,
val duration: Int,
val type: Int,
val neighbourIDs: MutableList<Int>,
val simID: Int,
val specificNumber: String,
val specificType: String,
val isUnknownNumber: Boolean,
) {
fun doesContainPhoneNumber(text: String): Boolean {
val normalizedText = text.normalizePhoneNumber()

View File

@ -1,6 +1,5 @@
package com.simplemobiletools.dialer.services
import android.net.Uri
import android.os.Build
import android.telecom.Call
import android.telecom.CallScreeningService
@ -15,17 +14,27 @@ import com.simplemobiletools.commons.helpers.SimpleContactsHelper
class SimpleCallScreeningService : CallScreeningService() {
override fun onScreenCall(callDetails: Call.Details) {
val number = Uri.decode(callDetails.handle?.toString())?.substringAfter("tel:")
if (number != null && isNumberBlocked(number.normalizePhoneNumber())) {
respondToCall(callDetails, isBlocked = true)
} else if (number != null && baseConfig.blockUnknownNumbers) {
val simpleContactsHelper = SimpleContactsHelper(this)
val privateCursor = getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true)
simpleContactsHelper.exists(number, privateCursor) { exists ->
respondToCall(callDetails, isBlocked = !exists)
val number = callDetails.handle?.schemeSpecificPart
when {
number != null && isNumberBlocked(number.normalizePhoneNumber()) -> {
respondToCall(callDetails, isBlocked = true)
}
number != null && baseConfig.blockUnknownNumbers -> {
val simpleContactsHelper = SimpleContactsHelper(this)
val privateCursor = getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true)
simpleContactsHelper.exists(number, privateCursor) { exists ->
respondToCall(callDetails, isBlocked = !exists)
}
}
number == null && baseConfig.blockHiddenNumbers -> {
respondToCall(callDetails, isBlocked = true)
}
else -> {
respondToCall(callDetails, isBlocked = false)
}
} else {
respondToCall(callDetails, isBlocked = false)
}
}

View File

@ -282,7 +282,7 @@
android:layout_width="@dimen/dialpad_button_size"
android:layout_height="@dimen/dialpad_button_size"
android:contentDescription="@string/end_call"
android:src="@drawable/ic_call_decline"
android:src="@drawable/ic_call_end"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@ -318,7 +318,7 @@
android:clickable="false"
android:contentDescription="@string/decline_call"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_call_decline"
android:src="@drawable/ic_call_end"
app:layout_constraintBottom_toBottomOf="@+id/call_draggable"
app:layout_constraintEnd_toStartOf="@+id/call_draggable"
app:layout_constraintHorizontal_bias="0.5"

View File

@ -393,6 +393,47 @@
android:text="@string/show_incoming_calls_full_screen" />
</RelativeLayout>
<include
android:id="@+id/settings_migration_divider"
layout="@layout/divider" />
<TextView
android:id="@+id/settings_migration_section_label"
style="@style/SettingsSectionLabelStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/migrating" />
<RelativeLayout
android:id="@+id/settings_export_calls_holder"
style="@style/SettingsHolderTextViewOneLinerStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/settings_export_calls"
style="@style/SettingsTextLabelStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/export_call_history" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_import_calls_holder"
style="@style/SettingsHolderTextViewOneLinerStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/settings_import_calls"
style="@style/SettingsTextLabelStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/import_call_history" />
</RelativeLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/export_contacts_scrollview"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/export_call_history_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="@dimen/activity_margin">
<com.simplemobiletools.commons.views.MyTextInputLayout
android:id="@+id/export_call_history_filename_hint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/medium_margin"
android:hint="@string/filename_without_json"
android:paddingStart="@dimen/activity_margin"
android:paddingEnd="@dimen/activity_margin">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/export_call_history_filename"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:textCursorDrawable="@null"
android:textSize="@dimen/bigger_text_size" />
</com.simplemobiletools.commons.views.MyTextInputLayout>
</LinearLayout>
</ScrollView>

View File

@ -5,10 +5,33 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.simplemobiletools.commons.views.MySearchMenu
android:id="@+id/contact_search_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/medium_margin"
android:paddingTop="@dimen/medium_margin" />
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/contacts_empty_placeholder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/contact_search_view"
android:alpha="0.8"
android:gravity="center_horizontal"
android:paddingStart="@dimen/activity_margin"
android:paddingTop="@dimen/activity_margin"
android:paddingEnd="@dimen/activity_margin"
android:text="@string/no_contacts_found"
android:textSize="@dimen/bigger_text_size"
android:textStyle="italic"
android:visibility="gone" />
<com.simplemobiletools.commons.views.MyRecyclerView
android:id="@+id/select_contact_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/contacts_empty_placeholder"
android:clipToPadding="false"
android:scrollbars="none"
app:layoutManager="com.simplemobiletools.commons.views.MyLinearLayoutManager" />
@ -17,6 +40,7 @@
android:id="@+id/letter_fastscroller"
android:layout_width="32dp"
android:layout_height="wrap_content"
android:layout_below="@+id/contact_search_view"
android:layout_alignParentEnd="true"
android:paddingTop="@dimen/big_margin"
android:paddingBottom="@dimen/big_margin" />
@ -29,5 +53,4 @@
android:layout_alignBottom="@+id/letter_fastscroller"
android:layout_marginEnd="@dimen/activity_margin"
android:layout_toStartOf="@+id/letter_fastscroller" />
</RelativeLayout>

View File

@ -33,9 +33,9 @@
android:layout_marginEnd="@dimen/small_margin"
android:ellipsize="end"
android:maxLines="1"
android:textSize="@dimen/bigger_text_size"
android:textDirection="locale"
android:textAlignment="viewStart"
android:textDirection="locale"
android:textSize="@dimen/bigger_text_size"
app:layout_constraintBottom_toTopOf="@id/item_recents_date_time"
app:layout_constraintEnd_toStartOf="@+id/overflow_menu_icon"
app:layout_constraintStart_toEndOf="@+id/item_recents_image"

View File

@ -31,6 +31,11 @@
android:showAsAction="always"
android:title="@string/send_sms"
app:showAsAction="always" />
<item
android:id="@+id/cab_block_unblock_contact"
android:icon="@drawable/ic_minus_circle_vector"
android:title="@string/block_contact"
app:showAsAction="ifRoom" />
<item
android:id="@+id/cab_create_shortcut"
android:showAsAction="never"

View File

@ -24,6 +24,16 @@
android:icon="@drawable/ic_delete_vector"
android:title="@string/clear_call_history"
app:showAsAction="always" />
<item
android:id="@+id/change_view_type"
android:icon="@drawable/ic_change_view_vector"
android:title="@string/change_view_type"
app:showAsAction="ifRoom" />
<item
android:id="@+id/column_count"
android:icon="@drawable/ic_column_count_vector"
android:title="@string/column_count"
app:showAsAction="ifRoom" />
<item
android:id="@+id/settings"
android:icon="@drawable/ic_settings_cog_vector"

View File

@ -72,6 +72,8 @@
<string name="disable_swipe_to_answer">استبدل التمرير عند الرد على المكالمات الواردة بالنقر</string>
<string name="show_incoming_calls_full_screen">عرض المكالمات الواردة دائما في وضع ملء الشاشة</string>
<string name="hide_dialpad_numbers">اخفي ارقام لوحت المفاتيح</string>
<string name="export_call_history">تصدير سجل المكالمات</string>
<string name="import_call_history">استيراد سجل المكالمات</string>
<!-- FAQ -->
<string name="faq_1_title">أسمع مكالمات واردة، ولكن الشاشة لا تعمل. ماذا أفعل؟</string>
<string name="faq_1_text">يمكن أن يكون لمثل هذه المشكلات العديد من الأسباب الخاصة بالجهاز والنظام ، والتي يصعب تحديدها بشكل عام. يجب أن تنظر حولك في إعدادات جهازك وتأكد من السماح للتطبيق بالظهور عندما يكون في الخلفية والسماح بالعرض فوق التطبيقات الأخرى.</string>

View File

@ -72,10 +72,13 @@
<string name="disable_swipe_to_answer">Replace swiping at responding to incoming calls with clicking</string>
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res

View File

@ -20,8 +20,8 @@
<string name="asterisk">Зорачка</string>
<string name="hashtag">Рашотка</string>
<string name="call_number">Нумар выкліку</string>
<string name="dialpad_beeps">Enable beeps on dialpad button clicks</string>
<string name="dialpad_vibrations">Enable vibrations on dialpad button clicks</string>
<string name="dialpad_beeps">Уключыць гукавыя сігналы пры націсканні кнопак панэлі набору</string>
<string name="dialpad_vibrations">Уключыць вібрацыю пры націсканні кнопак панэлі набору</string>
<!-- Dialer -->
<string name="dialer">Тэлефон</string>
<string name="accept">Прыняць</string>
@ -72,10 +72,13 @@
<string name="disable_swipe_to_answer">Выкарыстоўваць націсканне замест перацягвання пры адказе на ўваходныя выклікі</string>
<string name="show_incoming_calls_full_screen">Заўсёды паказваць уваходныя выклікі ў поўнаэкранным рэжыме</string>
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res

View File

@ -20,8 +20,8 @@
<string name="asterisk">Звездичка</string>
<string name="hashtag">Диез</string>
<string name="call_number">Номер</string>
<string name="dialpad_beeps">Enable beeps on dialpad button clicks</string>
<string name="dialpad_vibrations">Enable vibrations on dialpad button clicks</string>
<string name="dialpad_beeps">Активиране на звукови сигнали при докосване на бутоните на клавиатурата за набиране</string>
<string name="dialpad_vibrations">Активиране на вибрации при докосване на бутоните на клавиатурата за набиране</string>
<!-- Dialer -->
<string name="dialer">Телефон</string>
<string name="accept">Приемане</string>
@ -54,13 +54,13 @@
<string name="call_add">Добавяне на обаждане</string>
<string name="conference_manage">Управление на конферентен разговор</string>
<string name="conference">Конференция</string>
<string name="audio_route_speaker">Speaker</string>
<string name="audio_route_earpiece">Earpiece</string>
<string name="audio_route_speaker">Високоговорител</string>
<string name="audio_route_earpiece">Слушалки</string>
<string name="audio_route_bluetooth">Bluetooth</string>
<string name="audio_route_wired_headset">Wired Headset</string>
<string name="audio_route_wired_or_earpiece">Wired or Earpiece</string>
<string name="choose_audio_route">Choose audio route</string>
<string name="calling_blocked_number">The number you are calling is blocked</string>
<string name="audio_route_wired_headset">Слушалки с кабел</string>
<string name="audio_route_wired_or_earpiece">Жични или безжични слушалки</string>
<string name="choose_audio_route">Изберете аудио източник</string>
<string name="calling_blocked_number">Номерът, на който звъните, е блокиран</string>
<!-- Speed dial -->
<string name="speed_dial">Бързо набиране</string>
<string name="manage_speed_dial">Управление на бързото набиране</string>
@ -70,14 +70,15 @@
<string name="open_dialpad_by_default">При стартиране се отваря панела за набиране</string>
<string name="disable_proximity_sensor">Изключване на сензора за близост по време на обаждания</string>
<string name="disable_swipe_to_answer">Смяна на плъзгането с докосване при отговаряне на обаждания</string>
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
<string name="show_incoming_calls_full_screen">Винаги показвай входящите повиквания на цял екран</string>
<string name="hide_dialpad_numbers">Скриване на номерата на клавиатурата за набиране</string>
<string name="export_call_history">Експортиране на хронология на обажданията</string>
<string name="import_call_history">Импортиране на хронология на обажданията</string>
<!-- FAQ -->
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
<string name="faq_1_title">Чувам входящи повиквания, но екранът не се включва. Какво мога да направя\?</string>
<string name="faq_1_text">Такива проблеми могат да имат много специфични за устройството и системата причини, трудно е да се каже като цяло. Трябва да се огледате в настройките на вашето устройство и да се уверите, че на приложението е разрешено да изскача, когато е във фонов режим и да позволява показване върху други приложения.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View File

@ -72,6 +72,8 @@
<string name="disable_swipe_to_answer">Substitueix el lliscament en respondre a les trucades entrants per fer clic</string>
<string name="show_incoming_calls_full_screen">Mostra sempre les trucades entrants a pantalla completa</string>
<string name="hide_dialpad_numbers">Oculta els números del teclat numèric</string>
<string name="export_call_history">Exporta l\'historial de trucades</string>
<string name="import_call_history">Importa l\'historial de trucades</string>
<!-- FAQ -->
<string name="faq_1_title">Sento trucades entrants, però la pantalla no s\'encén. Què puc fer\?</string>
<string name="faq_1_text">Aquests problemes poden tenir moltes raons específiques del dispositiu i del sistema, difícils de dir en general. Hauríeu de mirar per la configuració del dispositiu i assegurar-vos que l\'aplicació pugui aparèixer en segon pla i permetre que es mostri sobre altres aplicacions.</string>

View File

@ -60,7 +60,7 @@
<string name="audio_route_wired_headset">Náhlavní souprava s kabelem</string>
<string name="audio_route_wired_or_earpiece">Kabel nebo sluchátka</string>
<string name="choose_audio_route">Vybrat směrování zvuku</string>
<string name="calling_blocked_number">The number you are calling is blocked</string>
<string name="calling_blocked_number">Číslo, které voláte, je blokované</string>
<!-- Speed dial -->
<string name="speed_dial">Rychlé vytáčení</string>
<string name="manage_speed_dial">Spravovat rychlá vytáčení</string>
@ -71,8 +71,9 @@
<string name="disable_proximity_sensor">Vypnout senzor přiblížení během hovoru</string>
<string name="disable_swipe_to_answer">Nahradit přejetí prstem při odpovídání na příchozí hovory za klepnutí</string>
<string name="show_incoming_calls_full_screen">Vždy zobrazovat příchozí hovory na celou obrazovku</string>
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
<string name="hide_dialpad_numbers">Skrýt čísla číselníku</string>
<string name="export_call_history">Exportovat historii volání</string>
<string name="import_call_history">Importovat historii volání</string>
<!-- FAQ -->
<string name="faq_1_title">Slyším příchozí hovor, ale obrazovka se nezapne. Co mohu dělat\?</string>
<string name="faq_1_text">Takové problémy mohou mít mnoho důvodů specifických pro zařízení a systém, takže je těžké říci něco obecně. Měli byste zkontrolovat nastavení zařízení a ujistit se, že se aplikace může otevřít, když běží na pozadí, a umožnit zobrazení přes jiné aplikace.</string>

View File

@ -72,10 +72,13 @@
<string name="disable_swipe_to_answer">Erstat swipe ved besvarelse af indgående opkald med at klikke på</string>
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
<!--
Kan du ikke finde nogle strenge? Der er mere på
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res

View File

@ -5,10 +5,10 @@
<string name="default_phone_app_prompt">Bitte machen Sie diese Anwendung zur Standard-Telefonanwendung</string>
<string name="allow_displaying_over_other_apps">Bitte erlauben Sie die Anzeige über andere Anwendungen für ein zuverlässiges Verhalten</string>
<!-- Contacts -->
<string name="could_not_access_contacts">Kein Zugriff auf Kontakte</string>
<string name="could_not_access_contacts">Kein Zugriff auf deine Kontakte möglich</string>
<!-- Recents -->
<string name="no_previous_calls">Anrufliste ist leer</string>
<string name="could_not_access_the_call_history">Kein Zugriff auf Anrufliste</string>
<string name="could_not_access_the_call_history">Kein Zugriff auf die Anrufliste möglich</string>
<string name="request_access">Zugriff anfordern</string>
<string name="remove_confirmation">Sollen wirklich die ausgewählten Einträge aus der Anrufliste gelöscht werden\?</string>
<string name="clear_history_confirmation">Soll wirklich die gesamte Anrufliste gelöscht werden\?</string>
@ -48,7 +48,7 @@
<string name="hold_call">Anruf halten</string>
<string name="resume_call">Anruf fortsetzen</string>
<string name="call_on_hold">In der Warteschleife</string>
<string name="call_swap">Anrufe austauschen</string>
<string name="call_swap">Anrufe wechseln</string>
<string name="call_merge">Anrufe zusammenführen</string>
<string name="call_split">Anruf teilen</string>
<string name="call_add">Anruf hinzufügen</string>
@ -70,8 +70,10 @@
<string name="open_dialpad_by_default">Beim Öffnen der App immer das Wähltastenfeld öffnen</string>
<string name="disable_proximity_sensor">Näherungssensor bei Anrufen deaktivieren</string>
<string name="disable_swipe_to_answer">Anrufe durch Klicken statt durch Streichen annehmen</string>
<string name="show_incoming_calls_full_screen">Eingehende Anrufe immer im Vollbildmodus anzeigen</string>
<string name="show_incoming_calls_full_screen">Eingehende Anrufe immer im Vollbild anzeigen</string>
<string name="hide_dialpad_numbers">Wähltastenfeld-Nummern ausblenden</string>
<string name="export_call_history">Anrufliste exportieren</string>
<string name="import_call_history">Anrufliste importieren</string>
<!-- FAQ -->
<string name="faq_1_title">Ich höre eingehende Anrufe, aber der Bildschirm schaltet sich nicht ein. Was kann ich tun\?</string>
<string name="faq_1_text">Eine allgemeine Antwort auf die Frage ist schwer, denn solche Probleme können viele geräte- und systemspezifische Gründe haben. Du solltest dich in den Einstellungen des Geräts umsehen und sicherstellen, dass die App im Hintergrund angezeigt werden darf und die Einblendung über anderen Apps erlaubt ist.</string>

View File

@ -72,11 +72,15 @@
<string name="disable_swipe_to_answer">Αντικατάσταση Σάρωσης με Κλικ στην απάντηση εισερχόμενων κλήσεων</string>
<string name="show_incoming_calls_full_screen">Να εμφανίζονται πάντα οι εισερχόμενες κλήσεις σε πλήρη οθόνη</string>
<string name="hide_dialpad_numbers">Απόκρυψη αριθμών πληκτρολογίου</string>
<string name="export_call_history">Εξαγωγή ιστορικού κλήσεων</string>
<string name="import_call_history">Εισαγωγή ιστορικού κλήσεων</string>
<!-- FAQ -->
<string name="faq_1_title">Ακούω εισερχόμενες κλήσεις, αλλά η οθόνη δεν ανάβει. Τι μπορώ να κάνω;</string>
<string name="faq_1_text">Τέτοια θέματα μπορεί να έχουν πολλούς λόγους που σχετίζονται με τη συσκευή και το σύστημα, και είναι δύσκολο να ειπωθούν γενικά. Θα πρέπει να ψάξετε στις ρυθμίσεις της συσκευής σας και να βεβαιωθείτε ότι η εφαρμογή επιτρέπεται να εμφανίζεται όταν βρίσκεται στο παρασκήνιο και να επιτρέπει την εμφάνισή της πάνω από άλλες εφαρμογές.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View File

@ -72,10 +72,13 @@
<string name="disable_swipe_to_answer">Replace swiping at responding to incoming calls with clicking</string>
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res

View File

@ -72,6 +72,8 @@
<string name="disable_swipe_to_answer">Reemplazar deslizar para responder llamadas entrantes a pulsar</string>
<string name="show_incoming_calls_full_screen">Siempre mostrar llamadas entrantes en pantalla completa</string>
<string name="hide_dialpad_numbers">Ocultar los números del teclado</string>
<string name="export_call_history">Exportar el historial de llamadas</string>
<string name="import_call_history">Importar el historial de llamadas</string>
<!-- FAQ -->
<string name="faq_1_title">Escucho las llamadas entrantes, pero la pantalla no se enciende. ¿Qué puedo hacer\?</string>
<string name="faq_1_text">Estos problemas pueden deberse a muchas razones específicas del dispositivo y del sistema, es difícil decirlo en general. Deberías mirar en la configuración de tu dispositivo y asegurarte de que la aplicación tiene permiso para aparecer cuando está en segundo plano y permitir la aplicación se muestre sobre otras aplicaciones.</string>

View File

@ -70,11 +70,13 @@
<string name="open_dialpad_by_default">Rakenduse avamisel näita vaikimisi numbriklahvistikku</string>
<string name="disable_proximity_sensor">Kõnede ajaks lülita lähedusandur välja</string>
<string name="disable_swipe_to_answer">Kõnele vastamisel kasuta viipamise asemel klõpsimist</string>
<string name="show_incoming_calls_full_screen">Kuvage sissetulevad kõned alati täisekraanil</string>
<string name="show_incoming_calls_full_screen">Alati näita sissetulevad kõned täisekraanivaates</string>
<string name="hide_dialpad_numbers">Peida numbriklahvistik</string>
<string name="export_call_history">Ekspordi kõnede ajalugu</string>
<string name="import_call_history">Impordi kõnede ajalugu</string>
<!-- FAQ -->
<string name="faq_1_title">Ma kuulen sissetulevaid kõnesid, kuid ekraan ei lülitu sisse. Mida ma saan teha\?</string>
<string name="faq_1_text">Sellistel probleemidel võib olla palju seadme- ja süsteemispetsiifilisi põhjusi, raske öelda üldiselt. Peaksite oma seadme seadetes ringi vaatama ja veenduma, et rakendusel on lubatud taustal hüpata ja lubada kuvamist üle teiste rakenduste.</string>
<string name="faq_1_text">Üldist vastust pole, sellistel probleemidel võib olla palju seadme- ja süsteemispetsiifilisi põhjusi. Peaksid oma nutiseadme seadistustes ringi vaatama ja veenduma, et rakendusel on lubatud taustalt aknaid avada ja lubada kuvamist rakenduste peal.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">تلفن ساده</string>
<string name="app_launcher_name">تلفن</string>
<string name="default_phone_app_prompt">لطفا این برنامه را به عنوان پیش‌گزیده تنظیم کنید</string>
<string name="allow_displaying_over_other_apps">برای عملکرد صحیح برنامه لطفا اجازه دهید روی برنامه‌های دیگر نمایش داده شود</string>
<!-- Contacts -->
<string name="could_not_access_contacts">دسترسی به مخاطبین شما امکان‌پذیر نیست</string>
<!-- Recents -->
<string name="no_previous_calls">هیچ تماس قبلی پیدا نشد</string>
<string name="could_not_access_the_call_history">دسترسی به تاریخچهٔ تماس شما امکان‌پذیر نیست</string>
<string name="request_access">درخواست دسترسی</string>
<string name="remove_confirmation">مطمئنید که می‌خواهید مورد انتخاب شده را از تاریخچه تماس حدف کنید؟</string>
<string name="clear_history_confirmation">مطمئنید که می‌خواهید تمام تاریخچه تماس حدف کنید؟</string>
<string name="show_grouped_calls">نمایش تماس‌های گروه‌بندی شده</string>
<string name="clear_call_history">پاک کردن تاریخچه تماس</string>
<string name="show_call_details">نمایش اطلاعات تماس</string>
<!-- Dialpad -->
<string name="dialpad">شماره‌گیر</string>
<string name="asterisk">ستاره</string>
<string name="hashtag">مربع</string>
<string name="call_number">شماره تماس</string>
<string name="dialpad_beeps">فعال کردن صدا هنگام لمس دکمه‌های شماره‌گیر</string>
<string name="dialpad_vibrations">فعال کردن لرزش هنگام لمس دکمه‌های شماره‌گیر</string>
<!-- Dialer -->
<string name="dialer">تلفن</string>
<string name="accept">پذیرش</string>
<string name="accept_call">پذیرفتن تماس</string>
<string name="decline">نپذیرفتن</string>
<string name="decline_call">نپذیرفتن تماس</string>
<string name="unknown_caller">تماس ناشناس</string>
<string name="is_calling">تماس گرفته…</string>
<string name="dialing">شماره‌گیری…</string>
<string name="call_ended">تماس پایان یافت</string>
<string name="call_ending">پایان دادن مکالمه</string>
<string name="ongoing_call">تماس در حال انجام</string>
<string name="select_sim">انتخاب سیم‌کارت برای تماس</string>
<string name="always_use_this_sim">برای این شماره همیشه از همین سیم‌کارت استفاده کن</string>
<string name="unset_default_sim">برداشتن سیم‌کارت پیش‌فرض</string>
<string name="calls">تماس‌ها</string>
<string name="turn_microphone_on">روشن کردن میکروفون</string>
<string name="turn_microphone_off">خاموش کردن میکروفون</string>
<string name="turn_speaker_on">روشن کردن بلندگو</string>
<string name="turn_speaker_off">خاموش کردن بلندگو</string>
<string name="show_dialpad">نمایش شماره‌گیر</string>
<string name="hide_dialpad">بستن شماره‌گیر</string>
<string name="end_call">پایان تماس</string>
<string name="hold_call">انتظار تماس</string>
<string name="resume_call">ادامه تماس</string>
<string name="call_on_hold">در انتظار</string>
<string name="call_swap">Swap calls</string>
<string name="call_merge">Merge calls</string>
<string name="call_split">Split call</string>
<string name="call_add">افزودن تماس</string>
<string name="conference_manage">Manage conference call</string>
<string name="conference">Conference</string>
<string name="audio_route_speaker">بلندگو</string>
<string name="audio_route_earpiece">هدفون</string>
<string name="audio_route_bluetooth">بلوتوث</string>
<string name="audio_route_wired_headset">هدست سیمی</string>
<string name="audio_route_wired_or_earpiece">سیمی یا هدفون</string>
<string name="choose_audio_route">انتخاب مسیر صدا</string>
<string name="calling_blocked_number">شماره‌ای که با آن تماس گرفته‌اید مسدود است</string>
<!-- Speed dial -->
<string name="speed_dial">شماره‌گیری سریع</string>
<string name="manage_speed_dial">مدیریت شماره‌گیری سریع</string>
<string name="speed_dial_label">یک شماره را انتخاب کنید تا مخاطبی را به آن اختصاص دهید. با لمس طولانی آن شماره در شماره‌گیر می‌توانید به سرعت با آن تماس بگیرید.</string>
<!-- Settings -->
<string name="group_subsequent_calls">گروه‌بندی تماس‌های پشت‌هم از یک شماره در تاریخچهٔ تماس</string>
<string name="open_dialpad_by_default">باز کردن شماره‌گیر به طور پیش‌فرض هنگام باز شدن برنامه</string>
<string name="disable_swipe_to_answer">پاسخ دادن به تماس با استفاده از کلیک به جای کشیدن</string>
<string name="disable_proximity_sensor">غیرفعال کردن حسگر مجاورت هنگام مکالمه</string>
<string name="show_incoming_calls_full_screen">تماس‌های ورودی همیشه بصورت تمام‌صفحه نمایش داده شوند</string>
<string name="hide_dialpad_numbers">مخفی کردن اعداد شماره‌گیر</string>
<string name="export_call_history">خروجی گرفتن تاریخچهٔ تماس</string>
<string name="import_call_history">وارد کردن تاریخچهٔ تماس</string>
<!-- FAQ -->
<string name="faq_1_title">من صدای تماس ورودی را می‌شنوم اما نمایشگر روشن نمی‌شود. باید چه کاری انجام دهم؟</string>
<string name="faq_1_text">این مشکل ممکن است بسته به دلایل مشکلات مختلفی در دستگاه و سامانه رخ دهد، بنابراین جواب کلی برای آن سخت است. باید تنظیمات دستگاهتان را بررسی کنید و مطمئن شوید که برنامه اجازه دارد در پس‌زمینه اجرا شود و روی برنامه‌های دیگر نمایش داده شود.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>

View File

@ -72,6 +72,8 @@
<string name="disable_swipe_to_answer">Vastaa puheluihin painalluksella pyyhkäisyn sijaan</string>
<string name="show_incoming_calls_full_screen">Näytä saapuvat puhelut aina koko näytöllä</string>
<string name="hide_dialpad_numbers">Piilota numeronäppäimet</string>
<string name="export_call_history">Vie puheluhistoria</string>
<string name="import_call_history">Tuo puheluhistoria</string>
<!-- FAQ -->
<string name="faq_1_title">Kuulen saapuvat puhelut, mutta näyttö on pimeänä. Mitä voin tehdä\?</string>
<string name="faq_1_text">Tällaisiin ongelmiin voi olla monia laite- ja järjestelmäkohtaisia syitä, joiden yleistäminen on hankalaa. Kannattaa tutkia laitteen asetuksia ja varmistaa, että sovelluksella on oikeus ponnahtaa esiin taustalta ja näkyä muiden sovellusten päällä.</string>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Simple Téléphone</string>
<string name="app_name">Téléphone simple</string>
<string name="app_launcher_name">Téléphone</string>
<string name="default_phone_app_prompt">Veuillez faire de cette application votre application de téléphone par défaut</string>
<string name="allow_displaying_over_other_apps">Veuillez permettre l\'affichage sur d\'autres applications pour un comportement fiable</string>
@ -20,10 +20,10 @@
<string name="asterisk">Étoile</string>
<string name="hashtag">Dièse</string>
<string name="call_number">Numéro d\'appel</string>
<string name="dialpad_beeps">Activer les bips lors des clics sur les boutons du clavier numérique</string>
<string name="dialpad_vibrations">Activation des vibrations lors des clics sur les boutons du clavier</string>
<string name="dialpad_beeps">Activer les sons lors de l\'appui sur les touches du pavé numérique</string>
<string name="dialpad_vibrations">Activer les vibrations lors de l\'appui sur les touches du pavé numérique</string>
<!-- Dialer -->
<string name="dialer">Clavier</string>
<string name="dialer">Pavé numérique</string>
<string name="accept">Accepter</string>
<string name="accept_call">Accepter l\'appel</string>
<string name="decline">Décliner</string>
@ -42,8 +42,8 @@
<string name="turn_microphone_off">Désactiver le microphone</string>
<string name="turn_speaker_on">Activer le haut-parleur</string>
<string name="turn_speaker_off">Désactiver le haut-parleur</string>
<string name="show_dialpad">Afficher le clavier</string>
<string name="hide_dialpad">Masquer le clavier</string>
<string name="show_dialpad">Afficher le pavé numérique</string>
<string name="hide_dialpad">Masquer le pavé numérique</string>
<string name="end_call">Finir l\'appel</string>
<string name="hold_call">Mettre l\'appel en attente</string>
<string name="resume_call">Reprendre l\'appel</string>
@ -71,7 +71,9 @@
<string name="disable_proximity_sensor">Désactiver le capteur de proximité pendant les appels</string>
<string name="disable_swipe_to_answer">Remplacer le balayage pour répondre aux appels entrants par un clic</string>
<string name="show_incoming_calls_full_screen">Toujours afficher les appels entrants en plein écran</string>
<string name="hide_dialpad_numbers">Masquer les numéros du clavier</string>
<string name="hide_dialpad_numbers">Masquer les numéros du pavé numérique</string>
<string name="export_call_history">Exporter l\'historique d\'appels</string>
<string name="import_call_history">Importer l\'historique d\'appels</string>
<!-- FAQ -->
<string name="faq_1_title">J\'entends les appels entrants, mais l\'écran ne s\'allume pas. Que puis-je faire \?</string>
<string name="faq_1_text">Ces problèmes peuvent avoir de nombreuses raisons spécifiques à l\'appareil et au système, il est difficile d\'en parler en général. Vous devriez consulter les paramètres de votre appareil et vous assurer que l\'application est autorisée à apparaître en arrière-plan et à s\'afficher au-dessus des autres applications.</string>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Simple Dialer</string>
<string name="app_name">Simple Marcador</string>
<string name="app_launcher_name">Marcador</string>
<string name="default_phone_app_prompt">Fai que sexa a aplición do Teléfono por predeterminada</string>
<string name="allow_displaying_over_other_apps">Permite mostrala por riba doutras aplicacións para un comportamento fiable</string>
@ -72,6 +72,8 @@
<string name="disable_swipe_to_answer">Substituír o xesto de desprazar por un click para responder</string>
<string name="show_incoming_calls_full_screen">Mostrar sempre as chamadas entrantes a pantalla enteira</string>
<string name="hide_dialpad_numbers">Ocultalos números do teclado</string>
<string name="export_call_history">Exportar historial de chamadas</string>
<string name="import_call_history">Importar historial de chamadas</string>
<!-- FAQ -->
<string name="faq_1_title">Escoito chamadas entrantes, pero a pantalla non se acende. Que podo facer\?</string>
<string name="faq_1_text">Estes problemas poden ter moitas razóns específicas do dispositivo e do sistema, difíciles de dicir en xeral. Debes mirar ao teu redor na configuración do teu dispositivo e asegurarte de que a aplicación pode aparecer cando está en segundo plano e permitir que se vexa sobre outras aplicacións.</string>
@ -79,4 +81,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View File

@ -3,7 +3,7 @@
<string name="app_name">Jednostavan birač</string>
<string name="app_launcher_name">Birač</string>
<string name="default_phone_app_prompt">Postavi ovu aplikaciju kao standardnu aplikaciju za telefon</string>
<string name="allow_displaying_over_other_apps">Za pouzdano ponašanje birača dopusti prikaz ispred drugih aplikacija</string>
<string name="allow_displaying_over_other_apps">Za pouzdano ponašanje dozvoli prikazivanje ispred drugih aplikacija</string>
<!-- Contacts -->
<string name="could_not_access_contacts">Nije moguće pristupiti tvojim kontaktima</string>
<!-- Recents -->
@ -69,14 +69,17 @@
<string name="group_subsequent_calls">Grupiraj naknadne pozive s istim brojem u zapisniku poziva</string>
<string name="open_dialpad_by_default">Otvori brojčanik prema zadanim postavkama kada se aplikacija otvori</string>
<string name="disable_proximity_sensor">Isključi senzor blizine tijekom poziva</string>
<string name="disable_swipe_to_answer">Zamijeni povlačenje prstom za odgovaranje na dolazne pozive pritiskom</string>
<string name="disable_swipe_to_answer">Prihvati pozive dodirom umjesto povlačenjem</string>
<string name="show_incoming_calls_full_screen">Uvijek prikaži dolazne pozive u cjeloekranskom prikazu</string>
<string name="hide_dialpad_numbers">Sakrij brojeve tipkovnice telefona</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">Čujem dolazne pozive, ali ekran se ne uključuje. Što mogu učiniti\?</string>
<string name="faq_1_title">Čujem dolazne pozive, ali se ekran ne uključuje. Što mogu učiniti\?</string>
<string name="faq_1_text">Takvi problemi mogu imati mnogo razloga specifičnih za uređaj i sustav, koje je teško reći općenito. Trebali biste pogledati uokolo u postavkama svog uređaja i provjeriti je li aplikaciji dopušteno iskakanje u pozadini i dopuštenje prikazivanja preko drugih aplikacija.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View File

@ -72,11 +72,15 @@
<string name="disable_swipe_to_answer">Csúsztatás kattintásra cserélése a bejövő hívásoknál</string>
<string name="show_incoming_calls_full_screen">Bejövő hívások megjelenítése mindig teljes képernyőn</string>
<string name="hide_dialpad_numbers">Tárcsázószámok elrejtése</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">Bejövő hívást hallok, de a képernyő nem kapcsol be. Mit tehetek\?</string>
<string name="faq_1_text">Az ilyen problémáknak számos eszköz- és rendszerfüggő oka lehet, általánosságban nehéz megmondani. Nézzen körül az eszközbeállításokban, és győződjön meg róla, hogy az alkalmazás előbújhat-e a háttérből, és megjelenhet-e más alkalmazások felett.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View File

@ -72,11 +72,15 @@
<string name="disable_swipe_to_answer">Ganti menggesek saat menanggapi panggilan masuk dengan mengklik</string>
<string name="show_incoming_calls_full_screen">Selalu tampilkan panggilan masuk dengan layar penuh</string>
<string name="hide_dialpad_numbers">Sembunyikan nomor tombol papan</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">Saya mendengar panggilan masuk, tetapi layarnya tidak menyala\? Apa yang bisa saya lakukan\?</string>
<string name="faq_1_text">Beberapa masalah dapat memiliki alasan perangkat dan sistem spesifik, tidak mudah untuk diberi tahu secara umum. Anda seharusnya melihat dalam pengaturan perangkat Anda dan memastikan bahwa aplikasi diperbolehkan untuk muncul ketika dalam latar belakang dan memperbolehkan menampilkan di atas aplikasi lain.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View File

@ -72,6 +72,8 @@
<string name="disable_swipe_to_answer">Sostituisci lo scorrimento nel rispondere alle chiamate in arrivo con un clic</string>
<string name="show_incoming_calls_full_screen">Visualizza sempre le chiamate in arrivo a schermo intero</string>
<string name="hide_dialpad_numbers">Nascondi i numeri del tastierino</string>
<string name="export_call_history">Esporta la cronologia delle chiamate</string>
<string name="import_call_history">Importa la cronologia delle chiamate</string>
<!-- FAQ -->
<string name="faq_1_title">Sento le chiamate in arrivo, ma lo schermo non si accende. Cosa posso fare\?</string>
<string name="faq_1_text">Tali problemi possono avere molte ragioni specifiche per il dispositivo e il sistema, è difficile identificarle in generale. Dovresti dare un\'occhiata alle impostazioni del dispositivo e assicurarti che l\'app sia autorizzata a comparire quando è in background e che permetta la visualizzazione sopra le altre app.</string>

View File

@ -72,10 +72,13 @@
<string name="disable_swipe_to_answer">החלף החלקה בתגובה לשיחות נכנסות בלחיצה</string>
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res

View File

@ -72,11 +72,15 @@
<string name="disable_swipe_to_answer">着信に応答する際のスワイプ操作をタップ操作に置き換える</string>
<string name="show_incoming_calls_full_screen">着信通知を常に全画面で表示する</string>
<string name="hide_dialpad_numbers">ダイヤルパッドの番号を表示しない</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">着信音は聞こえるのですが、画面がつきません。どうしたらよいですか?</string>
<string name="faq_1_text">このような問題は、端末やシステム固有の理由が多く、一概には言えません。端末の設定を見て、アプリがバックグラウンドでポップアップすることを許可しているか、他のアプリの上に表示することを許可しているかを確認する必要があります。</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View File

@ -72,10 +72,13 @@
<string name="disable_swipe_to_answer">Atsiliepiant į įeinančius skambučius perbraukimą pakeiskite paspaudimu</string>
<string name="show_incoming_calls_full_screen">Visada rodykite įeinančius skambučius per visą ekraną</string>
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res

View File

@ -72,9 +72,13 @@
<string name="disable_swipe_to_answer">ഇൻകമിംഗ് കോളുകളോട് പ്രതികരിക്കുമ്പോൾ സ്വൈപ്പിംഗ് മാറ്റി പകരം ഇൻകമിംഗ് കോളിൽ ക്ലിക്ക് ചെയ്യുക</string>
<string name="show_incoming_calls_full_screen">എല്ലായ്‌പ്പോഴും ഇൻകമിംഗ് കോളുകൾ പൂർണ്ണ സ്‌ക്രീനിൽ പ്രദർശിപ്പിക്കുക</string>
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">ഞാൻ ഇൻകമിംഗ് കോളുകൾ കേൾക്കുന്നു, പക്ഷേ സ്ക്രീൻ ഓണാക്കുന്നില്ല. എനിക്ക് എന്ത് ചെയ്യാൻ കഴിയും\?</string>
<string name="faq_1_text">അത്തരം പ്രശ്നങ്ങൾക്ക് ഉപകരണത്തിനും സിസ്റ്റത്തിനും പ്രത്യേക കാരണങ്ങളുണ്ടാകാം, പൊതുവായി പറയാൻ പ്രയാസമാണ്. നിങ്ങളുടെ ഉപകരണ ക്രമീകരണങ്ങളിൽ നിങ്ങൾ ചുറ്റും നോക്കുകയും പശ്ചാത്തലത്തിലായിരിക്കുമ്പോൾ ആപ്പ് പോപ്പ് അപ്പ് ചെയ്യാൻ അനുവദിക്കുകയും മറ്റ് ആപ്പുകളിൽ പ്രദർശിപ്പിക്കാൻ അനുവദിക്കുകയും വേണം.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res

View File

@ -72,10 +72,13 @@
<string name="disable_swipe_to_answer">Erstatt sveiping ved å svare på innkommende anrop med å klikke</string>
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res

View File

@ -34,9 +34,9 @@
<string name="call_ended">Gesprek beëindigd</string>
<string name="call_ending">Einde gesprek</string>
<string name="ongoing_call">Huidig gesprek</string>
<string name="select_sim">Kies een SIM-kaart voor dit gesprek</string>
<string name="always_use_this_sim">Altijd deze SIM voor dit nummer gebruiken</string>
<string name="unset_default_sim">Standaard-SIM uitzetten</string>
<string name="select_sim">Kies een simkaart voor dit gesprek</string>
<string name="always_use_this_sim">Altijd deze simkaart voor dit nummer gebruiken</string>
<string name="unset_default_sim">Geen standaard-simkaart</string>
<string name="calls">Gesprekken</string>
<string name="turn_microphone_on">Microfoon inschakelen</string>
<string name="turn_microphone_off">Microfoon uitschakelen</string>
@ -72,6 +72,8 @@
<string name="disable_swipe_to_answer">Vervang vegen door klikken bij het aannemen van gesprekken</string>
<string name="show_incoming_calls_full_screen">Inkomende gesprekken altijd op volledig scherm tonen</string>
<string name="hide_dialpad_numbers">Toetsenblokcijfers verbergen</string>
<string name="export_call_history">Gespreksgeschiedenis exporteren</string>
<string name="import_call_history">Gespreksgeschiedenis importeren</string>
<!-- FAQ -->
<string name="faq_1_title">Ik hoor dat er een gesprek binnenkomt, maar het scherm gaat niet aan. Wat kan ik doen\?</string>
<string name="faq_1_text">Dit soort problemen kan vele oorzaken hebben, specifiek voor bepaalde apparaten en software. Controleer in ieder geval of voor deze app in de systeeminstellingen \"Weergeven vóór andere apps\" is toegestaan en of bij meldingen voor inkomende gesprekken \"Weergeven op scherm\" is ingeschakeld.</string>

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Simple Dialer</string>
<string name="app_launcher_name">Dialer</string>
<string name="default_phone_app_prompt">Please make this app the default Phone app</string>
<string name="allow_displaying_over_other_apps">Please allow displaying over other apps for reliable behaviour</string>
<!-- Contacts -->
<string name="could_not_access_contacts">Could not access your contacts</string>
<!-- Recents -->
<string name="no_previous_calls">No previous calls have been found</string>
<string name="could_not_access_the_call_history">Could not access the call history</string>
<string name="request_access">Request access</string>
<string name="remove_confirmation">Are you sure you want to remove the selected items from the Call History?</string>
<string name="clear_history_confirmation">Are you sure you want to remove everything from the Call History?</string>
<string name="show_grouped_calls">Show grouped calls</string>
<string name="clear_call_history">Clear call history</string>
<string name="show_call_details">Show call details</string>
<!-- Dialpad -->
<string name="dialpad">Dialpad</string>
<string name="asterisk">Asterisk</string>
<string name="hashtag">Hashtag</string>
<string name="call_number">Call number</string>
<string name="dialpad_beeps">Enable beeps on dialpad button clicks</string>
<string name="dialpad_vibrations">Enable vibrations on dialpad button clicks</string>
<!-- Dialer -->
<string name="dialer">Dialer</string>
<string name="accept">Accept</string>
<string name="accept_call">Accept call</string>
<string name="decline">Decline</string>
<string name="decline_call">Decline call</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling…</string>
<string name="dialing">Dialing…</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>
<string name="select_sim">Select a SIM for this call</string>
<string name="always_use_this_sim">Always use this SIM for this number</string>
<string name="unset_default_sim">Unset default SIM</string>
<string name="calls">Calls</string>
<string name="turn_microphone_on">Turn microphone on</string>
<string name="turn_microphone_off">Turn microphone off</string>
<string name="turn_speaker_on">Turn speaker on</string>
<string name="turn_speaker_off">Turn speaker off</string>
<string name="show_dialpad">Show dialpad</string>
<string name="hide_dialpad">Hide dialpad</string>
<string name="end_call">End call</string>
<string name="hold_call">Hold call</string>
<string name="resume_call">Resume call</string>
<string name="call_on_hold">On Hold</string>
<string name="call_swap">Swap calls</string>
<string name="call_merge">Merge calls</string>
<string name="call_split">Split call</string>
<string name="call_add">Add call</string>
<string name="conference_manage">Manage conference call</string>
<string name="conference">Conference</string>
<string name="audio_route_speaker">Speaker</string>
<string name="audio_route_earpiece">Earpiece</string>
<string name="audio_route_bluetooth">Bluetooth</string>
<string name="audio_route_wired_headset">Wired Headset</string>
<string name="audio_route_wired_or_earpiece">Wired or Earpiece</string>
<string name="choose_audio_route">Choose audio route</string>
<string name="calling_blocked_number">The number you are calling is blocked</string>
<!-- Speed dial -->
<string name="speed_dial">Speed dial</string>
<string name="manage_speed_dial">Manage speed dial</string>
<string name="speed_dial_label">Click on a number to assign a contact to it. You can then quickly call the given contact by long pressing the given number at the dialer.</string>
<!-- Settings -->
<string name="group_subsequent_calls">Group subsequent calls with the same number at the call log</string>
<string name="open_dialpad_by_default">Open the dialpad by default when the app opens</string>
<string name="disable_proximity_sensor">Disable proximity sensor during calls</string>
<string name="disable_swipe_to_answer">Replace swiping at responding to incoming calls with clicking</string>
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>

View File

@ -72,8 +72,11 @@
<string name="disable_swipe_to_answer">Replace swiping at responding to incoming calls with clicking</string>
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do\?</string>
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
</resources>

View File

@ -72,6 +72,8 @@
<string name="disable_swipe_to_answer">Zastąp naciśnięciem gest przesunięcia do odpowiadania na połączenia przychodzące</string>
<string name="show_incoming_calls_full_screen">Zawsze wyświetlaj połączenia przychodzące na pełnym ekranie</string>
<string name="hide_dialpad_numbers">Ukryj cyfry panelu wybierania</string>
<string name="export_call_history">Eksportuj historię połączeń</string>
<string name="import_call_history">Importuj historię połączeń</string>
<!-- FAQ -->
<string name="faq_1_title">Słyszę połączenia przychodzące, ale ekran się nie włącza. Co mogę zrobić\?</string>
<string name="faq_1_text">Takie problemy mogą mieć wiele przyczyn specyficznych dla urządzenia i systemu; ogólnie trudno powiedzieć. Powinieneś/powinnaś rozejrzeć się w ustawieniach swojego urządzenia i upewnić się, że aplikacja może pojawiać się, gdy jest w tle, i wyświetlać się nad innymi aplikacjami.</string>

View File

@ -72,9 +72,13 @@
<string name="disable_swipe_to_answer">Clicar em vez de deslizar para responder chamadas</string>
<string name="show_incoming_calls_full_screen">Sempre exibir as chamadas recebidas em tela cheia</string>
<string name="hide_dialpad_numbers">Ocultar números do teclado</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">Ouço chamadas recebidas, mas a tela não liga. O que eu posso fazer?</string>
<string name="faq_1_text">Esses problemas podem ter muitos motivos específicos do dispositivo e do sistema, difíceis de dizer em geral. Você deve olhar em volta nas configurações do seu dispositivo e certificar-se de que o aplicativo pode aparecer quando estiver em segundo plano e permitir a exibição sobre outros aplicativos.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res

View File

@ -72,6 +72,8 @@
<string name="disable_swipe_to_answer">Clicar em vez de deslizar para atender</string>
<string name="show_incoming_calls_full_screen">Mostrar em ecrã completo as chamadas recebidas</string>
<string name="hide_dialpad_numbers">Ocultar números no marcador</string>
<string name="export_call_history">Exportar registo de chamadas</string>
<string name="import_call_history">Importar registo de chamadas</string>
<!-- FAQ -->
<string name="faq_1_title">Estou a ouvir som mas o ecrã não liga. O que posso fazer\?</string>
<string name="faq_1_text">Esses problemas podem ter muitos motivos específicos do dispositivo e do sistema, difíceis de dizer em geral. Aceda às definições do sistema e certifique-se de que concedeu as permissões necessárias tais como permitir exibição por cima das outras aplicações.</string>

View File

@ -72,10 +72,13 @@
<string name="disable_swipe_to_answer">Înlocuiți glisarea pentru a răspunde la apelurile primite cu o singură apăsare</string>
<string name="show_incoming_calls_full_screen">Afișați întotdeauna apelurile primite pe întreg ecranul</string>
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">Aud apelurile primite, dar ecranul nu se aprinde. Ce pot face\?</string>
<string name="faq_1_text">Aceste probleme pot avea multe motive specifice dispozitivului și sistemului, fiind greu de spus în general. Ar trebui să vă uitați în setările dispozitivului și să vă asigurați că aplicația este permisă să apară atunci când este în fundal și că permite afișarea peste alte aplicații.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res

View File

@ -72,11 +72,15 @@
<string name="disable_swipe_to_answer">Использовать нажатие вместо перетаскивания при ответе на входящие вызовы</string>
<string name="show_incoming_calls_full_screen">Всегда отображать входящие вызовы на полный экран</string>
<string name="hide_dialpad_numbers">Скрыть цифры на номеронабирателе</string>
<string name="export_call_history">Экспорт истории звонков</string>
<string name="import_call_history">Импорт истории звонков</string>
<!-- FAQ -->
<string name="faq_1_title">Я слышу сигналы входящих вызовов, но экран не включается. Что можно сделать\?</string>
<string name="faq_1_text">Такие проблемы могут иметь множество специфических для устройства и системы причин, о которых трудно говорить в общем. Следует проверить настройки устройства и убедиться, что приложению разрешено отображение всплывающих уведомлений в фоновом режиме и отображение поверх других приложений.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View File

@ -72,10 +72,12 @@
<string name="disable_swipe_to_answer">Nahradiť potiahnutie prstom pri odpovedaní na prichádzajúce hovory kliknutím</string>
<string name="show_incoming_calls_full_screen">Stále zobraziť prichádzajúce hovory na celú obrazovku</string>
<string name="hide_dialpad_numbers">Skryť čísla na číselníku</string>
<string name="export_call_history">Exportovať históriu volaní</string>
<string name="import_call_history">Importovať históriu volaní</string>
<!-- FAQ -->
<string name="faq_1_title">Počujem prichádzajúce hovory, obrazovka sa ale nezapne. Čo s tým?</string>
<string name="faq_1_text">Takéto problémy majú často dôvody špecifické pre dané zariadenie alebo systém, ťažko teda dať všeobecné riešenie. Mali by ste sa poobzerať v nasteniach zariadenia a uistiť sa, že apka má povolenie na zobrazovanie sa z pozadia a na zobrazovanie sa nad ostatnými apkami.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res

View File

@ -72,12 +72,15 @@
<string name="disable_swipe_to_answer">Pri odzivanju na dohodne klice zamenjajte poteg s prstom na odziv s klikanjem</string>
<string name="show_incoming_calls_full_screen">Dohodne klice vedno prikaži na celotnem zaslonu</string>
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">Slišim dohodne klice, vendar se zaslon ne vklopi. Kaj lahko storim\?</string>
<string name="faq_1_text">Takšne težave imajo lahko veliko razlogov, ki so specifični za napravo in sistem, zato jih je na splošno težko opredeliti. Oglejte si nastavitve naprave in se prepričajte, da je aplikaciji dovoljeno, da se prikaže, ko je v ozadju, in da omogoča prikaz nad drugimi aplikacijami.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View File

@ -72,8 +72,11 @@
<string name="disable_swipe_to_answer">Замените превлачење при одговарању на долазне позиве кликом</string>
<string name="show_incoming_calls_full_screen">Увек прикажи долазне позиве преко целог екрана</string>
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">Чујем долазне позиве, али екран се не укључује. Шта могу да урадим\?</string>
<string name="faq_1_text">Такви проблеми могу имати много специфичних разлога за уређај и систем, што је уопштено тешко рећи. Требало би да погледате около у подешавањима уређаја и уверите се да је апликацији дозвољено да искаче када је у позадини и да дозволи приказивање преко других апликација.</string>
</resources>

View File

@ -72,6 +72,8 @@
<string name="disable_swipe_to_answer">Ersätt svepning vid besvarande av inkommande samtal med tryckning</string>
<string name="show_incoming_calls_full_screen">Visa alltid inkommande samtal i helskärm</string>
<string name="hide_dialpad_numbers">Dölj knappsatsens siffror</string>
<string name="export_call_history">Exportera samtalshistorik</string>
<string name="import_call_history">Importera samtalshistorik</string>
<!-- FAQ -->
<string name="faq_1_title">Jag hör inkommande samtal men skärmen vaknar inte. Vad gör jag\?</string>
<string name="faq_1_text">Sådana problem kan bero specifikt på apparat eller ditt sytem, det är svårt att svara på generellt. Du bör kolla i dina inställningar och säkerställa att appen har behörighet att synas i förgrunden och tillåts att synas över andra appar.</string>

View File

@ -72,10 +72,13 @@
<string name="disable_swipe_to_answer">Replace swiping at responding to incoming calls with clicking</string>
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res

View File

@ -72,6 +72,8 @@
<string name="disable_swipe_to_answer">Gelen aramalara yanıt vermek için kaydırmayı tıklamayla değiştir</string>
<string name="show_incoming_calls_full_screen">Gelen aramaları her zaman tam ekranda görüntüle</string>
<string name="hide_dialpad_numbers">Tuş takımı numaralarını gizle</string>
<string name="export_call_history">Arama geçmişini dışa aktar</string>
<string name="import_call_history">Arama geçmişini içe aktar</string>
<!-- FAQ -->
<string name="faq_1_title">Gelen aramaları duyuyorum ama ekran açılmıyor. Ne yapabilirim\?</string>
<string name="faq_1_text">Bu tür sorunların aygıta ve sisteme özgü birçok nedeni olabilir, genel olarak söylemek zor. Aygıt ayarlarınıza bakmalı ve uygulamanın arka plandayken açılmasına ve diğer uygulamaların üzerinde görüntülenmesine izin verildiğinden emin olmalısınız.</string>

View File

@ -72,6 +72,8 @@
<string name="disable_swipe_to_answer">Замінити перетягування на натискання під час відповіді на вхідні виклики</string>
<string name="show_incoming_calls_full_screen">Завжди відображати вхідні дзвінки на весь екран</string>
<string name="hide_dialpad_numbers">Приховати номери цифрової клавіатури</string>
<string name="export_call_history">Експорт журналу дзвінків</string>
<string name="import_call_history">Імпорт історії дзвінків</string>
<!-- FAQ -->
<string name="faq_1_title">Я чую вхідні дзвінки, але екран не вмикається. Що я можу зробити\?</string>
<string name="faq_1_text">Такі проблеми можуть мати багато специфічних для пристрою та системи причин, важко сказати в цілому. Вам слід подивитися в налаштуваннях свого пристрою та переконатися, що застосунку дозволено відображати у фоновому режимі та дозволяти відображення над іншими застосунками.</string>

View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Trình quay số đơn giản</string>
<string name="app_launcher_name">Trình quay số</string>
<string name="default_phone_app_prompt">Vui lòng đặt ứng dụng này làm ứng dụng Điện thoại mặc định</string>
<string name="allow_displaying_over_other_apps">Vui lòng cho phép hiển thị trên các ứng dụng khác để có hành vi đáng tin cậy</string>
<!-- Contacts -->
<string name="could_not_access_contacts">Không thể truy cập danh bạ của bạn</string>
<!-- Recents -->
<string name="no_previous_calls">Không tìm thấy cuộc gọi nào trước đây</string>
<string name="could_not_access_the_call_history">Không vào được lịch sử cuộc gọi</string>
<string name="request_access">Yêu cầu quyền truy cập</string>
<string name="remove_confirmation">Bạn có chắc chắn muốn xóa các mục đã chọn khỏi Lịch sử cuộc gọi không\?</string>
<string name="clear_history_confirmation">Bạn có chắc chắn muốn xóa mọi thứ khỏi Lịch sử cuộc gọi không\?</string>
<string name="show_grouped_calls">Hiển thị các cuộc gọi được nhóm</string>
<string name="clear_call_history">Xóa lịch sử cuộc gọi</string>
<string name="show_call_details">Hiển thị chi tiết cuộc gọi</string>
<!-- Dialpad -->
<string name="dialpad">Bàn phím quay số</string>
<string name="asterisk">Dấu hoa thị</string>
<string name="hashtag">Dấu thăng</string>
<string name="call_number">Số điện thoại</string>
<string name="dialpad_beeps">Bật tiếng bíp khi bấm vào nút quay số</string>
<string name="dialpad_vibrations">Bật rung khi nhấp vào nút quay số</string>
<!-- Dialer -->
<string name="dialer">Trình quay số</string>
<string name="accept">Chấp nhận</string>
<string name="accept_call">Chấp nhận cuộc gọi</string>
<string name="decline">Từ chối</string>
<string name="decline_call">Từ chối cuộc gọi</string>
<string name="unknown_caller">Người gọi Không xác định</string>
<string name="is_calling">Đang gọi…</string>
<string name="dialing">Đang quay số…</string>
<string name="call_ended">Cuộc gọi kết thúc</string>
<string name="call_ending">Đang kết thúc cuộc gọi</string>
<string name="ongoing_call">Cuộc gọi đang diễn ra</string>
<string name="select_sim">Chọn một SIM cho cuộc gọi này</string>
<string name="always_use_this_sim">Luôn sử dụng SIM này cho số này</string>
<string name="unset_default_sim">Bỏ đặt SIM mặc định</string>
<string name="calls">Cuộc gọi</string>
<string name="turn_microphone_on">Bật micrô</string>
<string name="turn_microphone_off">Tắt micrô</string>
<string name="turn_speaker_on">Bật loa</string>
<string name="turn_speaker_off">Tắt loa</string>
<string name="show_dialpad">Hiển thị bàn phím quay số</string>
<string name="hide_dialpad">Ẩn bàn phím quay số</string>
<string name="end_call">Kết thúc cuộc gọi</string>
<string name="hold_call">Giữ cuộc gọi</string>
<string name="resume_call">Tiếp tục cuộc gọi</string>
<string name="call_on_hold">Đang chờ</string>
<string name="call_swap">Hoán đổi cuộc gọi</string>
<string name="call_merge">Hợp nhất các cuộc gọi</string>
<string name="call_split">Tách cuộc gọi</string>
<string name="call_add">Thêm cuộc gọi</string>
<string name="conference_manage">Quản lý cuộc gọi hội nghị</string>
<string name="conference">Hội nghị</string>
<string name="audio_route_speaker">Loa</string>
<string name="audio_route_earpiece">Ống nghe</string>
<string name="audio_route_bluetooth">Bluetooth</string>
<string name="audio_route_wired_headset">Tai nghe có dây</string>
<string name="audio_route_wired_or_earpiece">Có dây hoặc Tai nghe</string>
<string name="choose_audio_route">Chọn tuyến đường âm thanh</string>
<string name="calling_blocked_number">Số bạn đang gọi bị chặn</string>
<!-- Speed dial -->
<string name="speed_dial">Quay số nhanh</string>
<string name="manage_speed_dial">Quản lý quay số nhanh</string>
<string name="speed_dial_label">Bấm vào một số để chỉ định một số liên lạc cho nó. Sau đó, bạn có thể nhanh chóng gọi cho số liên lạc đã cho bằng cách nhấn và giữ số đã cho ở trình quay số.</string>
<!-- Settings -->
<string name="group_subsequent_calls">Nhóm các cuộc gọi tiếp theo với cùng một số trong nhật ký cuộc gọi</string>
<string name="open_dialpad_by_default">Mở bàn phím quay số theo mặc định khi mở ứng dụng</string>
<string name="disable_proximity_sensor">Tắt cảm biến tiệm cận trong khi gọi</string>
<string name="disable_swipe_to_answer">Thay thế thao tác vuốt khi trả lời cuộc gọi đến bằng thao tác nhấp</string>
<string name="show_incoming_calls_full_screen">Luôn hiển thị các cuộc gọi đến trên toàn màn hình</string>
<string name="hide_dialpad_numbers">Ẩn số bàn phím quay số</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">Tôi nghe thấy cuộc gọi đến, nhưng màn hình không bật. Tôi có thể làm gì\?</string>
<string name="faq_1_text">Những vấn đề như vậy có thể có nhiều lý do cụ thể của thiết bị và hệ thống, khó nói chung. Bạn nên xem trong cài đặt thiết bị của mình và đảm bảo rằng ứng dụng được phép bật lên khi ở chế độ nền và cho phép hiển thị trên các ứng dụng khác.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>

View File

@ -72,6 +72,8 @@
<string name="disable_swipe_to_answer">用点击代替滑动来接听来电</string>
<string name="show_incoming_calls_full_screen">始终全屏显示来电</string>
<string name="hide_dialpad_numbers">隐藏拨号盘号码</string>
<string name="export_call_history">导出通话记录</string>
<string name="import_call_history">导入通话记录</string>
<!-- FAQ -->
<string name="faq_1_title">我听到来电声音,但屏幕不亮。我该怎么办\?</string>
<string name="faq_1_text">这样的问题可能有很多设备和系统的具体原因,很难笼统地说。你应该查看你的设备设置,确保应用在后台时被允许弹出,并允许其显示在其他应用上方。</string>

View File

@ -2,82 +2,83 @@
<resources>
<string name="app_name">Simple Dialer</string>
<string name="app_launcher_name">Dialer</string>
<string name="default_phone_app_prompt">請將 app 設為預設的電話 app</string>
<string name="allow_displaying_over_other_apps">Please allow displaying over other apps for reliable behaviour</string>
<string name="default_phone_app_prompt">請將 app 設為預設的電話 app</string>
<string name="allow_displaying_over_other_apps">請允許在其他 app 上顯示以確保可靠的行為</string>
<!-- Contacts -->
<string name="could_not_access_contacts">無法存取您的通訊錄</string>
<string name="could_not_access_contacts">無法存取您的聯絡人</string>
<!-- Recents -->
<string name="no_previous_calls">No previous calls have been found</string>
<string name="could_not_access_the_call_history">無法存取通話歷史紀錄</string>
<string name="request_access">Request access</string>
<string name="remove_confirmation">您確定要從通話錄中移除所選的項目嗎?</string>
<string name="clear_history_confirmation">您確定要通話記錄中所有的項目嗎?</string>
<string name="no_previous_calls">找不到先前的通話紀錄</string>
<string name="could_not_access_the_call_history">無法存取通話紀錄</string>
<string name="request_access">請求存取權限</string>
<string name="remove_confirmation">您確定要從通話錄中移除所選的項目嗎?</string>
<string name="clear_history_confirmation">您確定要清除通話紀錄中的所有項目嗎?</string>
<string name="show_grouped_calls">顯示群組通話</string>
<string name="clear_call_history">清除通話</string>
<string name="show_call_details">顯示通話詳</string>
<string name="clear_call_history">清除通話</string>
<string name="show_call_details">顯示通話詳細資訊</string>
<!-- Dialpad -->
<string name="dialpad">Dialpad</string>
<string name="asterisk">Asterisk</string>
<string name="hashtag">Hashtag</string>
<string name="call_number">話號碼</string>
<string name="dialpad_beeps">Enable beeps on dialpad button clicks</string>
<string name="dialpad_vibrations">Enable vibrations on dialpad button clicks</string>
<string name="dialpad">撥號鍵盤</string>
<string name="asterisk">星號</string>
<string name="hashtag">井號</string>
<string name="call_number">撥打電話號碼</string>
<string name="dialpad_beeps">啟用撥號鍵盤按鈕點選的提示音</string>
<string name="dialpad_vibrations">啟用撥號鍵盤按鈕點選的震動</string>
<!-- Dialer -->
<string name="dialer">Dialer</string>
<string name="accept">Accept</string>
<string name="accept_call">Accept call</string>
<string name="decline">Decline</string>
<string name="decline_call">Decline call</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialer">撥號器</string>
<string name="accept">接受</string>
<string name="accept_call">接聽來電</string>
<string name="decline">拒絕</string>
<string name="decline_call">拒絕來電</string>
<string name="unknown_caller">未知來電者</string>
<string name="is_calling">正在撥打…</string>
<string name="dialing">撥號中……</string>
<string name="call_ended">通話結束</string>
<string name="call_ending">即將結束通話</string>
<string name="select_sim">選擇此通話的 SIM 卡</string>
<string name="ongoing_call">Ongoing Call</string>
<string name="always_use_this_sim">Always use this SIM for this number</string>
<string name="unset_default_sim">Unset default SIM</string>
<string name="calls">Calls</string>
<string name="turn_microphone_on">Turn microphone on</string>
<string name="turn_microphone_off">Turn microphone off</string>
<string name="turn_speaker_on">Turn speaker on</string>
<string name="turn_speaker_off">Turn speaker off</string>
<string name="show_dialpad">Show dialpad</string>
<string name="hide_dialpad">Hide dialpad</string>
<string name="end_call">End call</string>
<string name="hold_call">Hold call</string>
<string name="resume_call">Resume call</string>
<string name="call_on_hold">On Hold</string>
<string name="call_swap">Swap calls</string>
<string name="call_merge">Merge calls</string>
<string name="call_split">Split call</string>
<string name="call_add">Add call</string>
<string name="conference_manage">Manage conference call</string>
<string name="conference">Conference</string>
<string name="audio_route_speaker">Speaker</string>
<string name="audio_route_earpiece">Earpiece</string>
<string name="audio_route_bluetooth">Bluetooth</string>
<string name="audio_route_wired_headset">Wired Headset</string>
<string name="audio_route_wired_or_earpiece">Wired or Earpiece</string>
<string name="choose_audio_route">Choose audio route</string>
<string name="calling_blocked_number">The number you are calling is blocked</string>
<string name="call_ending">通話即將結束</string>
<string name="select_sim">選擇此通話的 SIM 卡</string>
<string name="ongoing_call">進行中的通話</string>
<string name="always_use_this_sim">總是使用此 SIM 卡撥打這個號碼</string>
<string name="unset_default_sim">取消設定預設 SIM 卡</string>
<string name="calls">通話</string>
<string name="turn_microphone_on">開啟麥克風</string>
<string name="turn_microphone_off">關閉麥克風</string>
<string name="turn_speaker_on">開啟免持聽筒</string>
<string name="turn_speaker_off">關閉免持聽筒</string>
<string name="show_dialpad">顯示撥號鍵盤</string>
<string name="hide_dialpad">隱藏撥號鍵盤</string>
<string name="end_call">結束通話</string>
<string name="hold_call">保留通話</string>
<string name="resume_call">恢復通話</string>
<string name="call_on_hold">保留中</string>
<string name="call_swap">切換通話</string>
<string name="call_merge">合併通話</string>
<string name="call_split">分割通話</string>
<string name="call_add">新增通話</string>
<string name="conference_manage">管理會議通話</string>
<string name="conference">會議通話</string>
<string name="audio_route_speaker">免持聽筒</string>
<string name="audio_route_earpiece">耳機</string>
<string name="audio_route_bluetooth">藍牙</string>
<string name="audio_route_wired_headset">有線耳機</string>
<string name="audio_route_wired_or_earpiece">有線或耳機</string>
<string name="choose_audio_route">選擇音訊路徑</string>
<string name="calling_blocked_number">您撥打的號碼已被封鎖</string>
<!-- Speed dial -->
<string name="speed_dial">Speed dial</string>
<string name="manage_speed_dial">Manage speed dial</string>
<string name="speed_dial_label">Click on a number to assign a contact to it. You can then quickly call the given contact by long pressing the given number at the dialer.</string>
<string name="speed_dial">快速撥號</string>
<string name="manage_speed_dial">管理快速撥號</string>
<string name="speed_dial_label">點選一個號碼以指定聯絡人。然後您可以在撥號器長按該號碼快速撥打給該聯絡人。</string>
<!-- Settings -->
<string name="group_subsequent_calls">Group subsequent calls with the same number at the call log</string>
<string name="open_dialpad_by_default">Open the dialpad by default when the app opens</string>
<string name="disable_proximity_sensor">Disable proximity sensor during calls</string>
<string name="disable_swipe_to_answer">Replace swiping at responding to incoming calls with clicking</string>
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
<string name="group_subsequent_calls">將通話紀錄中相同號碼的連續通話分組</string>
<string name="open_dialpad_by_default">當 app 開啟時預設開啟撥號鍵盤</string>
<string name="disable_proximity_sensor">通話時停用接近感應器</string>
<string name="disable_swipe_to_answer">用點選來取代滑動回應來電</string>
<string name="show_incoming_calls_full_screen">總是全螢幕顯示來電</string>
<string name="hide_dialpad_numbers">隱藏撥號鍵盤數字</string>
<string name="export_call_history">匯出通話紀錄</string>
<string name="import_call_history">匯入通話紀錄</string>
<!-- FAQ -->
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
<string name="faq_1_title">我聽到來電,但螢幕沒有亮起。我該怎麼辦?</string>
<string name="faq_1_text">這種問題可能有許多與裝置和系統特定的原因,一般來說很難確定。您應該查看您的裝置設定,並確保 app 被允許在背景時彈出並允許在其他 app 上顯示。</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View File

@ -78,10 +78,13 @@
<string name="disable_swipe_to_answer">Replace swiping at responding to incoming calls with clicking</string>
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
<string name="export_call_history">Export call history</string>
<string name="import_call_history">Import call history</string>
<!-- FAQ -->
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res

View File

@ -1,28 +0,0 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.7.10'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.3.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
maven { url 'https://jitpack.io' }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

5
build.gradle.kts Normal file
View File

@ -0,0 +1,5 @@
plugins {
alias(libs.plugins.android).apply(false)
alias(libs.plugins.kotlinAndroid).apply(false)
alias(libs.plugins.kotlinSerialization).apply(false)
}

View File

@ -0,0 +1,2 @@
* Fixed number presses during call
* Added some stability, translation and UX improvements

View File

@ -0,0 +1 @@
* Added some stability, translation and UX improvements

View File

@ -0,0 +1,3 @@
* Avoid showing contacts without a phone number
* Fixed multiple contact handling related glitches
* Added some stability, translation and UX improvements

Some files were not shown because too many files have changed in this diff Show More