├── .circleci └── config.yml ├── .gitignore ├── .gitmodules ├── .travis.yml ├── LICENSE ├── PinyinIME ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── aidl │ └── com │ │ └── android │ │ └── inputmethod │ │ └── pinyin │ │ └── IPinyinDecoderService.aidl │ ├── cpp │ ├── Android.mk │ ├── CMakeLists.txt │ ├── android │ │ └── com_android_inputmethod_pinyin_PinyinDecoderService.cpp │ ├── command │ │ ├── Makefile │ │ └── pinyinime_dictbuilder.cpp │ ├── data │ │ ├── rawdict_utf16_65105_freq.txt │ │ └── valid_utf16.txt │ ├── include │ │ ├── atomdictbase.h │ │ ├── dictbuilder.h │ │ ├── dictdef.h │ │ ├── dictlist.h │ │ ├── dicttrie.h │ │ ├── lpicache.h │ │ ├── matrixsearch.h │ │ ├── mystdlib.h │ │ ├── ngram.h │ │ ├── pinyinime.h │ │ ├── searchutility.h │ │ ├── spellingtable.h │ │ ├── spellingtrie.h │ │ ├── splparser.h │ │ ├── sync.h │ │ ├── userdict.h │ │ ├── utf16char.h │ │ └── utf16reader.h │ └── share │ │ ├── dictbuilder.cpp │ │ ├── dictlist.cpp │ │ ├── dicttrie.cpp │ │ ├── lpicache.cpp │ │ ├── matrixsearch.cpp │ │ ├── mystdlib.cpp │ │ ├── ngram.cpp │ │ ├── pinyinime.cpp │ │ ├── searchutility.cpp │ │ ├── spellingtable.cpp │ │ ├── spellingtrie.cpp │ │ ├── splparser.cpp │ │ ├── sync.cpp │ │ ├── userdict.cpp │ │ ├── utf16char.cpp │ │ └── utf16reader.cpp │ ├── java │ └── com │ │ └── android │ │ └── inputmethod │ │ └── pinyin │ │ ├── BalloonHint.java │ │ ├── CandidateView.java │ │ ├── CandidateViewListener.java │ │ ├── CandidatesContainer.java │ │ ├── ComposingView.java │ │ ├── EnglishInputProcessor.java │ │ ├── Environment.java │ │ ├── InputMethodServiceProxy.java │ │ ├── InputModeSwitcher.java │ │ ├── KeyMapDream.java │ │ ├── PinyinDecoderService.java │ │ ├── PinyinIME.java │ │ ├── Settings.java │ │ ├── SettingsActivity.java │ │ ├── SkbContainer.java │ │ ├── SkbPool.java │ │ ├── SkbTemplate.java │ │ ├── SoftKey.java │ │ ├── SoftKeyToggle.java │ │ ├── SoftKeyboard.java │ │ ├── SoftKeyboardView.java │ │ ├── SoundManager.java │ │ ├── SystemPropertiesProxy.java │ │ └── XmlKeyboardLoader.java │ └── res │ ├── drawable │ ├── app_icon.png │ ├── arrow_bg.xml │ ├── arrow_left.png │ ├── arrow_right.png │ ├── candidate_balloon_bg.9.png │ ├── candidate_hl_bg.png │ ├── candidates_area_bg.9.png │ ├── candidates_vertical_line.png │ ├── cands_container_bg.9.png │ ├── comma_full_icon.png │ ├── comma_full_popup_icon.png │ ├── composing_area_bg.9.png │ ├── composing_area_cursor.png │ ├── composing_hl_bg.png │ ├── delete_icon.png │ ├── delete_popup_icon.png │ ├── dun_icon.png │ ├── dun_popup_icon.png │ ├── emotion_icon_00.png │ ├── emotion_icon_00_popup.png │ ├── emotion_icon_01.png │ ├── emotion_icon_01_popup.png │ ├── emotion_icon_02.png │ ├── emotion_icon_02_popup.png │ ├── emotion_icon_03.png │ ├── emotion_icon_03_popup.png │ ├── emotion_icon_04.png │ ├── emotion_icon_04_popup.png │ ├── emotion_icon_05.png │ ├── emotion_icon_05_popup.png │ ├── emotion_icon_06.png │ ├── emotion_icon_06_popup.png │ ├── emotion_icon_10.png │ ├── emotion_icon_10_popup.png │ ├── emotion_icon_11.png │ ├── emotion_icon_11_popup.png │ ├── emotion_icon_12.png │ ├── emotion_icon_12_popup.png │ ├── emotion_icon_13.png │ ├── emotion_icon_13_popup.png │ ├── emotion_icon_14.png │ ├── emotion_icon_14_popup.png │ ├── emotion_icon_15.png │ ├── emotion_icon_15_popup.png │ ├── emotion_icon_16.png │ ├── emotion_icon_16_popup.png │ ├── emotion_icon_20.png │ ├── emotion_icon_20_popup.png │ ├── emotion_icon_21.png │ ├── emotion_icon_21_popup.png │ ├── emotion_icon_22.png │ ├── emotion_icon_22_popup.png │ ├── emotion_icon_23.png │ ├── emotion_icon_23_popup.png │ ├── emotion_icon_24.png │ ├── emotion_icon_24_popup.png │ ├── enter_icon.png │ ├── enter_popup_icon.png │ ├── ime_en.png │ ├── ime_pinyin.png │ ├── key_balloon_bg.9.png │ ├── light_key_bg.9.png │ ├── light_key_hl_bg.9.png │ ├── light_key_up_bg.9.png │ ├── light_key_up_hl_bg.9.png │ ├── miniskb_bg.9.png │ ├── normal_key_bg.9.png │ ├── normal_key_hl_bg.9.png │ ├── num0.png │ ├── num1.png │ ├── num2.png │ ├── num3.png │ ├── num4.png │ ├── num5.png │ ├── num6.png │ ├── num7.png │ ├── num8.png │ ├── num9.png │ ├── numalt.png │ ├── numpound.png │ ├── numstar.png │ ├── period_full_icon.png │ ├── period_full_popup_icon.png │ ├── period_icon.png │ ├── period_popup_icon.png │ ├── search_icon.png │ ├── search_popup_icon.png │ ├── shift_off_icon.png │ ├── shift_off_popup_icon.png │ ├── shift_on_icon.png │ ├── shift_on_popup_icon.png │ ├── skb_bg.png │ ├── skb_container_bg.9.png │ ├── smiley_icon.png │ ├── smiley_popup_icon.png │ ├── space_icon.png │ └── space_popup_icon.png │ ├── layout │ ├── candidates_container.xml │ ├── floating_container.xml │ └── skb_container.xml │ ├── raw │ └── dict_pinyin.dat │ ├── values-land │ └── dimens.xml │ ├── values-port │ └── dimens.xml │ ├── values │ ├── colors.xml │ ├── dimens.xml │ └── strings.xml │ └── xml │ ├── settings.xml │ ├── skb_phone.xml │ ├── skb_qwerty.xml │ ├── skb_smiley.xml │ ├── skb_sym1.xml │ ├── skb_sym2.xml │ └── skb_template1.xml ├── README.md ├── app ├── .gitignore └── build.gradle ├── appveyor.yml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── metadata └── com.dimension.tessercube.yml ├── privacy_policy.md ├── settings.gradle └── tessercubecore ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src ├── androidTest └── java │ └── com │ └── sujitech │ └── tessercubecore │ └── ExampleInstrumentedTest.kt ├── main ├── AndroidManifest.xml ├── ic_launcher_tessercube-web.png ├── java │ └── com │ │ └── sujitech │ │ └── tessercubecore │ │ ├── App.kt │ │ ├── activity │ │ ├── BaseActivity.kt │ │ ├── IndexActivity.kt │ │ ├── SettingsActivity.kt │ │ ├── SplashActivity.kt │ │ ├── TutorialActivity.kt │ │ ├── contact │ │ │ ├── ContactDetailActivity.kt │ │ │ ├── EditContactActivity.kt │ │ │ └── ImportContactActivity.kt │ │ ├── keypair │ │ │ ├── CreateKeyActivity.kt │ │ │ ├── ImportKeyActivity.kt │ │ │ └── InputPrivateKeyActivity.kt │ │ └── message │ │ │ ├── ComposeActivity.kt │ │ │ └── InterpretActivity.kt │ │ ├── common │ │ ├── Config.kt │ │ ├── Constants.kt │ │ ├── DataTracking.kt │ │ ├── FloatingHoverUtils.kt │ │ ├── IMEUtils.kt │ │ ├── MessageDataUtils.kt │ │ ├── OpenPGPUtils.kt │ │ ├── Settings.kt │ │ ├── UserPasswordStorage.kt │ │ ├── adapter │ │ │ ├── AutoAdapter.kt │ │ │ ├── ChildViewAdapter.kt │ │ │ └── FragmentAdapter.kt │ │ ├── collection │ │ │ ├── CollectionChangedEventArg.kt │ │ │ ├── CollectionChangedType.kt │ │ │ ├── IIncrementalSource.kt │ │ │ ├── ISupportIncrementalLoading.kt │ │ │ ├── IncrementalLoadingCollection.kt │ │ │ └── ObservableCollection.kt │ │ └── extension │ │ │ ├── Biometric.kt │ │ │ ├── ContextExtensions.kt │ │ │ ├── Extensions.kt │ │ │ ├── HexExtensions.kt │ │ │ ├── ImageExtension.kt │ │ │ └── pgpContentExtensions.kt │ │ ├── data │ │ ├── ContactData.kt │ │ └── DbContext.kt │ │ ├── fragment │ │ ├── ContactsFragment.kt │ │ ├── MeFragment.kt │ │ ├── MessagesFragment.kt │ │ └── ViewPagerFragment.kt │ │ ├── keyboard │ │ ├── KeyboardEncryptButton.kt │ │ ├── KeyboardEncryptToolBar.kt │ │ └── KeyboardExtendView.kt │ │ ├── service │ │ └── DummyAccountService.kt │ │ └── widget │ │ ├── BlockedViewPager.kt │ │ ├── CommandButton.kt │ │ ├── ContactView.kt │ │ ├── ImageSwitch.kt │ │ └── MessageCard.kt └── res │ ├── drawable-hdpi │ └── ic_launcher_foreground.png │ ├── drawable-mdpi │ └── ic_launcher_foreground.png │ ├── drawable-xhdpi │ └── ic_launcher_foreground.png │ ├── drawable-xxhdpi │ └── ic_launcher_foreground.png │ ├── drawable-xxxhdpi │ └── ic_launcher_foreground.png │ ├── drawable │ ├── ic_account_circle_black_24dp.xml │ ├── ic_add_black_24dp.xml │ ├── ic_brightness_1_black_24dp.xml │ ├── ic_chat_black_24dp.xml │ ├── ic_contract_name_background.xml │ ├── ic_dashboard_black_24dp.xml │ ├── ic_done_black_24dp.xml │ ├── ic_edit_black_24dp.xml │ ├── ic_home_black_24dp.xml │ ├── ic_keyboard_toggle_icon.xml │ ├── ic_lock_outline_black_24dp.xml │ ├── ic_notifications_black_24dp.xml │ ├── ic_people_black_24dp.xml │ ├── ic_person_black_24dp.xml │ ├── ic_round_border.xml │ ├── ic_search_black_24dp.xml │ ├── ic_splash.xml │ ├── ic_tutorial_1.png │ ├── ic_tutorial_2.png │ ├── ic_tutorial_3.png │ └── ic_vpn_key_black_24dp.xml │ ├── layout │ ├── activity_compose.xml │ ├── activity_contact_detail.xml │ ├── activity_create_key.xml │ ├── activity_edit_contact.xml │ ├── activity_import_contact.xml │ ├── activity_import_key.xml │ ├── activity_index.xml │ ├── activity_input_private_key.xml │ ├── activity_interpret.xml │ ├── activity_settings.xml │ ├── activity_tutorial.xml │ ├── dialog_add_contact.xml │ ├── dialog_loading.xml │ ├── empty_message.xml │ ├── floating_decrypt.xml │ ├── fragment_contacts.xml │ ├── fragment_me.xml │ ├── fragment_messages.xml │ ├── item_contact.xml │ ├── item_contact_empty.xml │ ├── item_keyboard_toolbar_contract.xml │ ├── item_me_key.xml │ ├── item_message_card.xml │ ├── item_message_contact.xml │ ├── view_keyboard_encrypt.xml │ ├── view_keyboard_interpret.xml │ ├── widget_command_button.xml │ ├── widget_contact.xml │ ├── widget_keyboard_encrypt_button.xml │ ├── widget_keyboard_encrypt_toolbar.xml │ ├── widget_keyboard_extend_view.xml │ └── widget_message_card.xml │ ├── menu │ ├── compose_toolbar.xml │ ├── contact_detail_toolbar.xml │ ├── contacts_toolbar.xml │ ├── edit_contact_toolbar.xml │ ├── index_bottom.xml │ ├── me_add_key.xml │ ├── me_toolbar.xml │ ├── me_user_key_recycler_view.xml │ ├── message_draft.xml │ ├── message_from_me.xml │ ├── message_from_others.xml │ └── messages_toolbar.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher_tessercube.xml │ └── ic_launcher_tessercube_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher_foreground.png │ ├── ic_launcher_tessercube.png │ └── ic_launcher_tessercube_round.png │ ├── mipmap-mdpi │ ├── ic_launcher_foreground.png │ ├── ic_launcher_tessercube.png │ └── ic_launcher_tessercube_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher_foreground.png │ ├── ic_launcher_tessercube.png │ └── ic_launcher_tessercube_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher_foreground.png │ ├── ic_launcher_tessercube.png │ └── ic_launcher_tessercube_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher_foreground.png │ ├── ic_launcher_tessercube.png │ └── ic_launcher_tessercube_round.png │ ├── values-ja │ └── strings.xml │ ├── values-ko │ └── strings.xml │ ├── values-night │ └── colors.xml │ ├── values-zh-rCN │ └── strings.xml │ ├── values-zh-rTW │ └── strings.xml │ ├── values │ ├── attrs_command_button.xml │ ├── colors.xml │ ├── config.xml │ ├── dimens.xml │ ├── ic_launcher_background.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ ├── account_preferences.xml │ ├── authenticator.xml │ └── root.xml └── test └── java └── com └── sujitech └── tessercubecore └── ExampleUnitTest.kt /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Android Studio Navigation editor temp files 30 | .navigation/ 31 | 32 | # Android Studio captures folder 33 | captures/ 34 | 35 | # IntelliJ 36 | *.iml 37 | .idea/workspace.xml 38 | .idea/tasks.xml 39 | .idea/gradle.xml 40 | .idea/dictionaries 41 | .idea/libraries 42 | 43 | # Keystore files 44 | # Uncomment the following line if you do not want to check your keystore files in. 45 | #*.jks 46 | 47 | # External native build folder generated in Android Studio 2.2 and later 48 | .externalNativeBuild 49 | 50 | # Google Services (e.g. APIs or Firebase) 51 | google-services.json 52 | 53 | # Freeline 54 | freeline.py 55 | freeline/ 56 | freeline_project_description.json 57 | 58 | \.idea/ 59 | 60 | \.circleci/keys/ 61 | 62 | .cxx 63 | .settings 64 | .project 65 | .classpath -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "inputmethodcommon"] 2 | path = inputmethodcommon 3 | url = https://android.googlesource.com/platform/frameworks/opt/inputmethodcommon 4 | branch = pie-platform-release 5 | [submodule "LatinIME"] 6 | path = LatinIME 7 | url = https://github.com/DimensionDev/LatinIME.git 8 | branch = pie-fork 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | 3 | android: 4 | components: 5 | - platform-tools 6 | - tools 7 | - build-tools-28.0.3 8 | - android-28 9 | - extra-android-m2repository 10 | - extra-google-m2repository 11 | - extra-android-support 12 | 13 | before_install: 14 | - chmod +x ./gradlew 15 | script: 16 | - echo y | sdkmanager "ndk-bundle" "platforms;android-28" 17 | - ./gradlew assembleDebug -------------------------------------------------------------------------------- /PinyinIME/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | //apply plugin: "com.android.application" 3 | 4 | android { 5 | compileSdkVersion target_version 6 | 7 | defaultConfig { 8 | minSdkVersion min_version 9 | targetSdkVersion target_version 10 | // applicationId "com.android.inputmethod.pinyin" 11 | 12 | externalNativeBuild { 13 | cmake { 14 | cppFlags "-Wall" 15 | } 16 | } 17 | } 18 | 19 | 20 | buildTypes { 21 | release { 22 | minifyEnabled false 23 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 24 | } 25 | } 26 | 27 | externalNativeBuild { 28 | cmake { 29 | path 'src/main/cpp/CMakeLists.txt' 30 | } 31 | } 32 | 33 | compileOptions { 34 | sourceCompatibility 1.8 35 | targetCompatibility 1.8 36 | } 37 | } 38 | 39 | dependencies { 40 | } -------------------------------------------------------------------------------- /PinyinIME/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /PinyinIME/src/main/aidl/com/android/inputmethod/pinyin/IPinyinDecoderService.aidl: -------------------------------------------------------------------------------- 1 | /* //com/andriod/inputmethod/pinyin/IPinyinDecoderService.aidl 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | package com.android.inputmethod.pinyin; 19 | 20 | interface IPinyinDecoderService { 21 | int getInt(); 22 | void setMaxLens(int maxSpsLen, int maxHzsLen); 23 | int imSearch(in byte[] pyBuf, int pyLen); 24 | int imDelSearch(int pos, boolean is_pos_in_splid, boolean clear_fixed_this_step); 25 | void imResetSearch(); 26 | int imAddLetter(byte ch); 27 | String imGetPyStr(boolean decoded); 28 | int imGetPyStrLen(boolean decoded); 29 | int[] imGetSplStart(); 30 | String imGetChoice(int choiceId); 31 | String imGetChoices(int choicesNum); 32 | List imGetChoiceList(int choicesStart, int choicesNum, int sentFixedLen); 33 | int imChoose(int choiceId); 34 | int imCancelLastChoice(); 35 | int imGetFixedLen(); 36 | boolean imCancelInput(); 37 | void imFlushCache(); 38 | int imGetPredictsNum(in String fixedStr); 39 | List imGetPredictList(int predictsStart, int predictsNum); 40 | String imGetPredictItem(int predictNo); 41 | 42 | String syncUserDict(in String tomerge); 43 | boolean syncBegin(); 44 | void syncFinish(); 45 | int syncPutLemmas(in String tomerge); 46 | String syncGetLemmas(); 47 | int syncGetLastCount(); 48 | int syncGetTotalCount(); 49 | void syncClearLastGot(); 50 | int imSyncGetCapacity(); 51 | } 52 | -------------------------------------------------------------------------------- /PinyinIME/src/main/cpp/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | ### shared library 4 | 5 | include $(CLEAR_VARS) 6 | 7 | LOCAL_SRC_FILES := \ 8 | android/com_android_inputmethod_pinyin_PinyinDecoderService.cpp \ 9 | share/dictbuilder.cpp \ 10 | share/dictlist.cpp \ 11 | share/dicttrie.cpp \ 12 | share/lpicache.cpp \ 13 | share/matrixsearch.cpp \ 14 | share/mystdlib.cpp \ 15 | share/ngram.cpp \ 16 | share/pinyinime.cpp \ 17 | share/searchutility.cpp \ 18 | share/spellingtable.cpp \ 19 | share/spellingtrie.cpp \ 20 | share/splparser.cpp \ 21 | share/userdict.cpp \ 22 | share/utf16char.cpp \ 23 | share/utf16reader.cpp \ 24 | share/sync.cpp 25 | 26 | LOCAL_C_INCLUDES += $(JNI_H_INCLUDE) 27 | LOCAL_MODULE := libjni_pinyinime 28 | #LOCAL_SHARED_LIBRARIES := libcutils libutils 29 | LOCAL_MODULE_TAGS := optional 30 | 31 | LOCAL_CFLAGS += -D_PLATFORM_ANDROID 32 | LOCAL_LDLIBS := -llog -landroid -lz 33 | 34 | include $(BUILD_SHARED_LIBRARY) 35 | APP_CFLAGS += -Wno-error=format-security 36 | -------------------------------------------------------------------------------- /PinyinIME/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | cmake_minimum_required(VERSION 3.4.1) 3 | 4 | add_library(jni_pinyinime SHARED 5 | android/com_android_inputmethod_pinyin_PinyinDecoderService.cpp 6 | share/dictbuilder.cpp 7 | share/dictlist.cpp 8 | share/dicttrie.cpp 9 | share/lpicache.cpp 10 | share/matrixsearch.cpp 11 | share/mystdlib.cpp 12 | share/ngram.cpp 13 | share/pinyinime.cpp 14 | share/searchutility.cpp 15 | share/spellingtable.cpp 16 | share/spellingtrie.cpp 17 | share/splparser.cpp 18 | share/userdict.cpp 19 | share/utf16char.cpp 20 | share/utf16reader.cpp 21 | share/sync.cpp) 22 | 23 | include_directories(src/main/cpp/include/) 24 | 25 | add_library(engine 26 | STATIC 27 | share/dictbuilder.cpp 28 | share/dictlist.cpp 29 | share/dicttrie.cpp 30 | share/lpicache.cpp 31 | share/mystdlib.cpp 32 | share/ngram.cpp 33 | share/searchutility.cpp 34 | share/spellingtable.cpp 35 | share/spellingtrie.cpp 36 | share/splparser.cpp 37 | share/utf16char.cpp 38 | share/utf16reader.cpp ) 39 | 40 | target_link_libraries(jni_pinyinime 41 | android 42 | log 43 | z 44 | engine) 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /PinyinIME/src/main/cpp/command/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS= -g -Wall -std=c99 3 | CPP=g++ 4 | CPPFLAGS= -g3 -Wall -lpthread 5 | 6 | PINYINIME_DICTBUILDER=pinyinime_dictbuilder 7 | 8 | LIBRARY_SRC= \ 9 | ../share/dictbuilder.cpp \ 10 | ../share/dictlist.cpp \ 11 | ../share/dicttrie.cpp \ 12 | ../share/lpicache.cpp \ 13 | ../share/mystdlib.cpp \ 14 | ../share/ngram.cpp \ 15 | ../share/searchutility.cpp \ 16 | ../share/spellingtable.cpp \ 17 | ../share/spellingtrie.cpp \ 18 | ../share/splparser.cpp \ 19 | ../share/utf16char.cpp \ 20 | ../share/utf16reader.cpp \ 21 | 22 | all: engine 23 | 24 | engine: $(PINYINIME_DICTBUILDER) 25 | 26 | $(PINYINIME_DICTBUILDER): $(LIBRARY_SRC) pinyinime_dictbuilder.cpp 27 | @$(CPP) $(CPPFLAGS) -o $@ $? 28 | 29 | 30 | clean: 31 | -rm -rf $(PINYINIME_DICTBUILDER) 32 | 33 | .PHONY: clean 34 | -------------------------------------------------------------------------------- /PinyinIME/src/main/cpp/command/pinyinime_dictbuilder.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include "../include/dicttrie.h" 23 | 24 | using namespace ime_pinyin; 25 | 26 | /** 27 | * Build binary dictionary model. Make sure that ___BUILD_MODEL___ is defined 28 | * in dictdef.h. 29 | */ 30 | int main(int argc, char* argv[]) { 31 | DictTrie* dict_trie = new DictTrie(); 32 | bool success; 33 | if (argc >= 3) 34 | success = dict_trie->build_dict(argv[1], argv[2]); 35 | else 36 | success = dict_trie->build_dict("../data/rawdict_utf16_65105_freq.txt", 37 | "../data/valid_utf16.txt"); 38 | 39 | if (success) { 40 | printf("Build dictionary successfully.\n"); 41 | } else { 42 | printf("Build dictionary unsuccessfully.\n"); 43 | return -1; 44 | } 45 | 46 | success = dict_trie->save_dict("../../res/raw/dict_pinyin.dat"); 47 | 48 | if (success) { 49 | printf("Save dictionary successfully.\n"); 50 | } else { 51 | printf("Save dictionary unsuccessfully.\n"); 52 | return -1; 53 | } 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /PinyinIME/src/main/cpp/data/rawdict_utf16_65105_freq.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/cpp/data/rawdict_utf16_65105_freq.txt -------------------------------------------------------------------------------- /PinyinIME/src/main/cpp/data/valid_utf16.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/cpp/data/valid_utf16.txt -------------------------------------------------------------------------------- /PinyinIME/src/main/cpp/include/lpicache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef PINYINIME_ANDPY_INCLUDE_LPICACHE_H__ 18 | #define PINYINIME_ANDPY_INCLUDE_LPICACHE_H__ 19 | 20 | #include 21 | #include "./searchutility.h" 22 | #include "./spellingtrie.h" 23 | 24 | namespace ime_pinyin { 25 | 26 | // Used to cache LmaPsbItem list for half spelling ids. 27 | class LpiCache { 28 | private: 29 | static LpiCache *instance_; 30 | static const int kMaxLpiCachePerId = 15; 31 | 32 | LmaPsbItem *lpi_cache_; 33 | uint16 *lpi_cache_len_; 34 | 35 | public: 36 | LpiCache(); 37 | ~LpiCache(); 38 | 39 | static LpiCache& get_instance(); 40 | 41 | // Test if the LPI list of the given splid has been cached. 42 | // If splid is a full spelling id, it returns false, because we only cache 43 | // list for half ids. 44 | bool is_cached(uint16 splid); 45 | 46 | // Put LPI list to cahce. If the length of the list, lpi_num, is longer than 47 | // the cache buffer. the list will be truncated, and function returns the 48 | // maximum length of the cache buffer. 49 | // Note: splid must be a half id, and lpi_items must be not NULL. The 50 | // caller of this function should guarantee this. 51 | size_t put_cache(uint16 splid, LmaPsbItem lpi_items[], size_t lpi_num); 52 | 53 | // Get the cached list for the given half id. 54 | // Return the length of the cached buffer. 55 | // Note: splid must be a half id, and lpi_items must be not NULL. The 56 | // caller of this function should guarantee this. 57 | size_t get_cache(uint16 splid, LmaPsbItem lpi_items[], size_t lpi_max); 58 | }; 59 | 60 | } // namespace 61 | 62 | #endif // PINYINIME_ANDPY_INCLUDE_LPICACHE_H__ 63 | -------------------------------------------------------------------------------- /PinyinIME/src/main/cpp/include/mystdlib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef PINYINIME_INCLUDE_MYSTDLIB_H__ 18 | #define PINYINIME_INCLUDE_MYSTDLIB_H__ 19 | 20 | #include 21 | 22 | namespace ime_pinyin { 23 | 24 | void myqsort(void *p, size_t n, size_t es, 25 | int (*cmp)(const void *, const void *)); 26 | 27 | void *mybsearch(const void *key, const void *base, 28 | size_t nmemb, size_t size, 29 | int (*compar)(const void *, const void *)); 30 | } 31 | 32 | #endif // PINYINIME_INCLUDE_MYSTDLIB_H__ 33 | -------------------------------------------------------------------------------- /PinyinIME/src/main/cpp/include/ngram.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef PINYINIME_INCLUDE_NGRAM_H__ 18 | #define PINYINIME_INCLUDE_NGRAM_H__ 19 | 20 | #include 21 | #include 22 | #include "./dictdef.h" 23 | 24 | namespace ime_pinyin { 25 | 26 | typedef unsigned char CODEBOOK_TYPE; 27 | 28 | static const size_t kCodeBookSize = 256; 29 | 30 | class NGram { 31 | public: 32 | // The maximum score of a lemma item. 33 | static const LmaScoreType kMaxScore = 0x3fff; 34 | 35 | // In order to reduce the storage size, the original log value is amplified by 36 | // kScoreAmplifier, and we use LmaScoreType to store. 37 | // After this process, an item with a lower score has a higher frequency. 38 | static const int kLogValueAmplifier = -800; 39 | 40 | // System words' total frequency. It is not the real total frequency, instead, 41 | // It is only used to adjust system lemmas' scores when the user dictionary's 42 | // total frequency changes. 43 | // In this version, frequencies of system lemmas are fixed. We are considering 44 | // to make them changable in next version. 45 | static const size_t kSysDictTotalFreq = 100000000; 46 | 47 | private: 48 | 49 | static NGram* instance_; 50 | 51 | bool initialized_; 52 | size_t idx_num_; 53 | 54 | size_t total_freq_none_sys_; 55 | 56 | // Score compensation for system dictionary lemmas. 57 | // Because after user adds some user lemmas, the total frequency changes, and 58 | // we use this value to normalize the score. 59 | float sys_score_compensation_; 60 | 61 | #ifdef ___BUILD_MODEL___ 62 | double *freq_codes_df_; 63 | #endif 64 | LmaScoreType *freq_codes_; 65 | CODEBOOK_TYPE *lma_freq_idx_; 66 | 67 | public: 68 | NGram(); 69 | ~NGram(); 70 | 71 | static NGram& get_instance(); 72 | 73 | bool save_ngram(FILE *fp); 74 | bool load_ngram(FILE *fp); 75 | 76 | // Set the total frequency of all none system dictionaries. 77 | void set_total_freq_none_sys(size_t freq_none_sys); 78 | 79 | float get_uni_psb(LemmaIdType lma_id); 80 | 81 | // Convert a probability to score. Actually, the score will be limited to 82 | // kMaxScore, but at runtime, we also need float expression to get accurate 83 | // value of the score. 84 | // After the conversion, a lower score indicates a higher probability of the 85 | // item. 86 | static float convert_psb_to_score(double psb); 87 | 88 | #ifdef ___BUILD_MODEL___ 89 | // For constructing the unigram mode model. 90 | bool build_unigram(LemmaEntry *lemma_arr, size_t num, 91 | LemmaIdType next_idx_unused); 92 | #endif 93 | }; 94 | } 95 | 96 | #endif // PINYINIME_INCLUDE_NGRAM_H__ 97 | -------------------------------------------------------------------------------- /PinyinIME/src/main/cpp/include/sync.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef PINYINIME_INCLUDE_SYNC_H__ 18 | #define PINYINIME_INCLUDE_SYNC_H__ 19 | 20 | #define ___SYNC_ENABLED___ 21 | 22 | #ifdef ___SYNC_ENABLED___ 23 | 24 | #include "userdict.h" 25 | 26 | namespace ime_pinyin { 27 | 28 | // Class for user dictionary synchronization 29 | // This class is not thread safe 30 | // Normal invoking flow will be 31 | // begin() -> 32 | // put_lemmas() x N -> 33 | // { 34 | // get_lemmas() -> 35 | // [ get_last_got_count() ] -> 36 | // clear_last_got() -> 37 | // } x N -> 38 | // finish() 39 | class Sync { 40 | public: 41 | Sync(); 42 | ~Sync(); 43 | 44 | static const int kUserDictMaxLemmaCount = 5000; 45 | static const int kUserDictMaxLemmaSize = 200000; 46 | static const int kUserDictRatio = 20; 47 | 48 | bool begin(const char * filename); 49 | 50 | // Merge lemmas downloaded from sync server into local dictionary 51 | // lemmas, lemmas string encoded in UTF16LE 52 | // len, length of lemmas string 53 | // Return how many lemmas merged successfully 54 | int put_lemmas(char16 * lemmas, int len); 55 | 56 | // Get local new user lemmas into UTF16LE string 57 | // str, buffer ptr to store new user lemmas 58 | // size, size of buffer 59 | // Return length of returned buffer in measure of UTF16LE 60 | int get_lemmas(char16 * str, int size); 61 | 62 | // Return lemmas count in last get_lemmas() 63 | int get_last_got_count(); 64 | 65 | // Return total lemmas count need get_lemmas() 66 | int get_total_count(); 67 | 68 | // Clear lemmas got by recent get_lemmas() 69 | void clear_last_got(); 70 | 71 | void finish(); 72 | 73 | int get_capacity(); 74 | 75 | private: 76 | UserDict * userdict_; 77 | char * dictfile_; 78 | int last_count_; 79 | }; 80 | 81 | } 82 | 83 | #endif 84 | 85 | #endif // PINYINIME_INCLUDE_SYNC_H__ 86 | -------------------------------------------------------------------------------- /PinyinIME/src/main/cpp/include/utf16char.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef PINYINIME_INCLUDE_UTF16CHAR_H__ 18 | #define PINYINIME_INCLUDE_UTF16CHAR_H__ 19 | 20 | #include 21 | 22 | namespace ime_pinyin { 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | typedef unsigned short char16; 29 | 30 | // Get a token from utf16_str, 31 | // Returned pointer is a '\0'-terminated utf16 string, or NULL 32 | // *utf16_str_next returns the next part of the string for further tokenizing 33 | char16* utf16_strtok(char16 *utf16_str, size_t *token_size, 34 | char16 **utf16_str_next); 35 | 36 | int utf16_atoi(const char16 *utf16_str); 37 | 38 | float utf16_atof(const char16 *utf16_str); 39 | 40 | size_t utf16_strlen(const char16 *utf16_str); 41 | 42 | int utf16_strcmp(const char16 *str1, const char16 *str2); 43 | int utf16_strncmp(const char16 *str1, const char16 *str2, size_t size); 44 | 45 | char16* utf16_strcpy(char16 *dst, const char16 *src); 46 | char16* utf16_strncpy(char16 *dst, const char16 *src, size_t size); 47 | 48 | 49 | char* utf16_strcpy_tochar(char *dst, const char16 *src); 50 | 51 | #ifdef __cplusplus 52 | } 53 | #endif 54 | } 55 | 56 | #endif // PINYINIME_INCLUDE_UTF16CHAR_H__ 57 | -------------------------------------------------------------------------------- /PinyinIME/src/main/cpp/include/utf16reader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef PINYINIME_INCLUDE_UTF16READER_H__ 18 | #define PINYINIME_INCLUDE_UTF16READER_H__ 19 | 20 | #include 21 | #include "./utf16char.h" 22 | 23 | namespace ime_pinyin { 24 | 25 | class Utf16Reader { 26 | private: 27 | FILE *fp_; 28 | char16 *buffer_; 29 | size_t buffer_total_len_; 30 | size_t buffer_next_pos_; 31 | 32 | // Always less than buffer_total_len_ - buffer_next_pos_ 33 | size_t buffer_valid_len_; 34 | 35 | public: 36 | Utf16Reader(); 37 | ~Utf16Reader(); 38 | 39 | // filename is the name of the file to open. 40 | // buffer_len specifies how long buffer should be allocated to speed up the 41 | // future reading 42 | bool open(const char* filename, size_t buffer_len); 43 | char16* readline(char16* read_buf, size_t max_len); 44 | bool close(); 45 | }; 46 | } 47 | 48 | #endif // PINYINIME_INCLUDE_UTF16READER_H__ 49 | -------------------------------------------------------------------------------- /PinyinIME/src/main/cpp/share/lpicache.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include "../include/lpicache.h" 19 | 20 | namespace ime_pinyin { 21 | 22 | LpiCache* LpiCache::instance_ = NULL; 23 | 24 | LpiCache::LpiCache() { 25 | lpi_cache_ = new LmaPsbItem[kFullSplIdStart * kMaxLpiCachePerId]; 26 | lpi_cache_len_ = new uint16[kFullSplIdStart]; 27 | assert(NULL != lpi_cache_); 28 | assert(NULL != lpi_cache_len_); 29 | for (uint16 id = 0; id < kFullSplIdStart; id++) 30 | lpi_cache_len_[id] = 0; 31 | } 32 | 33 | LpiCache::~LpiCache() { 34 | if (NULL != lpi_cache_) 35 | delete [] lpi_cache_; 36 | 37 | if (NULL != lpi_cache_len_) 38 | delete [] lpi_cache_len_; 39 | } 40 | 41 | LpiCache& LpiCache::get_instance() { 42 | if (NULL == instance_) { 43 | instance_ = new LpiCache(); 44 | assert(NULL != instance_); 45 | } 46 | return *instance_; 47 | } 48 | 49 | bool LpiCache::is_cached(uint16 splid) { 50 | if (splid >= kFullSplIdStart) 51 | return false; 52 | return lpi_cache_len_[splid] != 0; 53 | } 54 | 55 | size_t LpiCache::put_cache(uint16 splid, LmaPsbItem lpi_items[], 56 | size_t lpi_num) { 57 | uint16 num = kMaxLpiCachePerId; 58 | if (num > lpi_num) 59 | num = static_cast(lpi_num); 60 | 61 | LmaPsbItem *lpi_cache_this = lpi_cache_ + splid * kMaxLpiCachePerId; 62 | for (uint16 pos = 0; pos < num; pos++) 63 | lpi_cache_this[pos] = lpi_items[pos]; 64 | 65 | lpi_cache_len_[splid] = num; 66 | return num; 67 | } 68 | 69 | size_t LpiCache::get_cache(uint16 splid, LmaPsbItem lpi_items[], 70 | size_t lpi_max) { 71 | if (lpi_max > lpi_cache_len_[splid]) 72 | lpi_max = lpi_cache_len_[splid]; 73 | 74 | LmaPsbItem *lpi_cache_this = lpi_cache_ + splid * kMaxLpiCachePerId; 75 | for (uint16 pos = 0; pos < lpi_max; pos++) { 76 | lpi_items[pos] = lpi_cache_this[pos]; 77 | } 78 | return lpi_max; 79 | } 80 | 81 | } // namespace ime_pinyin 82 | -------------------------------------------------------------------------------- /PinyinIME/src/main/cpp/share/mystdlib.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | 19 | namespace ime_pinyin { 20 | 21 | // For debug purpose. You can add a fixed version of qsort and bsearch functions 22 | // here so that the output will be totally the same under different platforms. 23 | 24 | void myqsort(void *p, size_t n, size_t es, 25 | int (*cmp)(const void *, const void *)) { 26 | qsort(p,n, es, cmp); 27 | } 28 | 29 | void *mybsearch(const void *k, const void *b, 30 | size_t n, size_t es, 31 | int (*cmp)(const void *, const void *)) { 32 | return bsearch(k, b, n, es, cmp); 33 | } 34 | } // namespace ime_pinyin 35 | -------------------------------------------------------------------------------- /PinyinIME/src/main/cpp/share/sync.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "../include/sync.h" 18 | #include 19 | #include 20 | 21 | #ifdef ___SYNC_ENABLED___ 22 | 23 | namespace ime_pinyin { 24 | 25 | Sync::Sync() 26 | : userdict_(NULL), 27 | dictfile_(NULL), 28 | last_count_(0) { 29 | }; 30 | 31 | Sync::~Sync() { 32 | } 33 | 34 | 35 | bool Sync::begin(const char * filename) { 36 | if (userdict_) { 37 | finish(); 38 | } 39 | 40 | if (!filename) { 41 | return false; 42 | } 43 | 44 | dictfile_ = strdup(filename); 45 | if (!dictfile_) { 46 | return false; 47 | } 48 | 49 | userdict_ = new UserDict(); 50 | if (!userdict_) { 51 | free(dictfile_); 52 | dictfile_ = NULL; 53 | return false; 54 | } 55 | 56 | if (userdict_->load_dict((const char*)dictfile_, kUserDictIdStart, 57 | kUserDictIdEnd) == false) { 58 | delete userdict_; 59 | userdict_ = NULL; 60 | free(dictfile_); 61 | dictfile_ = NULL; 62 | return false; 63 | } 64 | 65 | userdict_->set_limit(kUserDictMaxLemmaCount, kUserDictMaxLemmaSize, kUserDictRatio); 66 | 67 | return true; 68 | } 69 | 70 | int Sync::put_lemmas(char16 * lemmas, int len) { 71 | return userdict_->put_lemmas_no_sync_from_utf16le_string(lemmas, len); 72 | } 73 | 74 | int Sync::get_lemmas(char16 * str, int size) { 75 | return userdict_->get_sync_lemmas_in_utf16le_string_from_beginning(str, size, &last_count_); 76 | } 77 | 78 | int Sync::get_last_got_count() { 79 | return last_count_; 80 | } 81 | 82 | int Sync::get_total_count() { 83 | return userdict_->get_sync_count(); 84 | } 85 | 86 | void Sync::clear_last_got() { 87 | if (last_count_ < 0) { 88 | return; 89 | } 90 | userdict_->clear_sync_lemmas(0, last_count_); 91 | last_count_ = 0; 92 | } 93 | 94 | void Sync::finish() { 95 | if (userdict_) { 96 | userdict_->close_dict(); 97 | delete userdict_; 98 | userdict_ = NULL; 99 | free(dictfile_); 100 | dictfile_ = NULL; 101 | last_count_ = 0; 102 | } 103 | } 104 | 105 | int Sync::get_capacity() { 106 | UserDict::UserDictStat stat; 107 | userdict_->state(&stat); 108 | return stat.limit_lemma_count - stat.lemma_count; 109 | } 110 | 111 | } 112 | #endif 113 | -------------------------------------------------------------------------------- /PinyinIME/src/main/java/com/android/inputmethod/pinyin/CandidateViewListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.inputmethod.pinyin; 18 | 19 | /** 20 | * Interface to notify the input method when the user clicks a candidate or 21 | * makes a direction-gesture on candidate view. 22 | */ 23 | public interface CandidateViewListener { 24 | public void onClickChoice(int choiceId); 25 | 26 | public void onToLeftGesture(); 27 | 28 | public void onToRightGesture(); 29 | 30 | public void onToTopGesture(); 31 | 32 | public void onToBottomGesture(); 33 | } 34 | -------------------------------------------------------------------------------- /PinyinIME/src/main/java/com/android/inputmethod/pinyin/SkbPool.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.inputmethod.pinyin; 18 | 19 | import java.util.Vector; 20 | 21 | import android.content.Context; 22 | 23 | /** 24 | * Class used to cache previously loaded soft keyboard layouts. 25 | */ 26 | public class SkbPool { 27 | private static SkbPool mInstance = null; 28 | 29 | private Vector mSkbTemplates = new Vector(); 30 | private Vector mSoftKeyboards = new Vector(); 31 | 32 | private SkbPool() { 33 | } 34 | 35 | public static SkbPool getInstance() { 36 | if (null == mInstance) mInstance = new SkbPool(); 37 | return mInstance; 38 | } 39 | 40 | public void resetCachedSkb() { 41 | mSoftKeyboards.clear(); 42 | } 43 | 44 | public SkbTemplate getSkbTemplate(int skbTemplateId, Context context) { 45 | for (int i = 0; i < mSkbTemplates.size(); i++) { 46 | SkbTemplate t = mSkbTemplates.elementAt(i); 47 | if (t.getSkbTemplateId() == skbTemplateId) { 48 | return t; 49 | } 50 | } 51 | 52 | if (null != context) { 53 | XmlKeyboardLoader xkbl = new XmlKeyboardLoader(context); 54 | SkbTemplate t = xkbl.loadSkbTemplate(skbTemplateId); 55 | if (null != t) { 56 | mSkbTemplates.add(t); 57 | return t; 58 | } 59 | } 60 | return null; 61 | } 62 | 63 | // Try to find the keyboard in the pool with the cache id. If there is no 64 | // keyboard found, try to load it with the given xml id. 65 | public SoftKeyboard getSoftKeyboard(int skbCacheId, int skbXmlId, 66 | int skbWidth, int skbHeight, Context context) { 67 | for (int i = 0; i < mSoftKeyboards.size(); i++) { 68 | SoftKeyboard skb = mSoftKeyboards.elementAt(i); 69 | if (skb.getCacheId() == skbCacheId && skb.getSkbXmlId() == skbXmlId) { 70 | skb.setSkbCoreSize(skbWidth, skbHeight); 71 | skb.setNewlyLoadedFlag(false); 72 | return skb; 73 | } 74 | } 75 | if (null != context) { 76 | XmlKeyboardLoader xkbl = new XmlKeyboardLoader(context); 77 | SoftKeyboard skb = xkbl.loadKeyboard(skbXmlId, skbWidth, skbHeight); 78 | if (skb != null) { 79 | if (skb.getCacheFlag()) { 80 | skb.setCacheId(skbCacheId); 81 | mSoftKeyboards.add(skb); 82 | } 83 | } 84 | return skb; 85 | } 86 | return null; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /PinyinIME/src/main/java/com/android/inputmethod/pinyin/SoundManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.inputmethod.pinyin; 18 | 19 | import android.content.Context; 20 | import android.media.AudioManager; 21 | 22 | /** 23 | * Class used to manage related sound resources. 24 | */ 25 | public class SoundManager { 26 | private static SoundManager mInstance = null; 27 | private Context mContext; 28 | private AudioManager mAudioManager; 29 | // Align sound effect volume on music volume 30 | private final float FX_VOLUME = -1.0f; 31 | private boolean mSilentMode; 32 | 33 | private SoundManager(Context context) { 34 | mContext = context; 35 | updateRingerMode(); 36 | } 37 | 38 | public void updateRingerMode() { 39 | if (mAudioManager == null) { 40 | mAudioManager = (AudioManager) mContext 41 | .getSystemService(Context.AUDIO_SERVICE); 42 | } 43 | mSilentMode = (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL); 44 | } 45 | 46 | public static SoundManager getInstance(Context context) { 47 | if (null == mInstance) { 48 | if (null != context) { 49 | mInstance = new SoundManager(context); 50 | } 51 | } 52 | return mInstance; 53 | } 54 | 55 | public void playKeyDown() { 56 | if (mAudioManager == null) { 57 | updateRingerMode(); 58 | } 59 | if (!mSilentMode) { 60 | int sound = AudioManager.FX_KEYPRESS_STANDARD; 61 | mAudioManager.playSoundEffect(sound, FX_VOLUME); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/app_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/arrow_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 19 | 21 | 22 | -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/arrow_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/arrow_left.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/arrow_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/arrow_right.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/candidate_balloon_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/candidate_balloon_bg.9.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/candidate_hl_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/candidate_hl_bg.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/candidates_area_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/candidates_area_bg.9.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/candidates_vertical_line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/candidates_vertical_line.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/cands_container_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/cands_container_bg.9.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/comma_full_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/comma_full_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/comma_full_popup_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/comma_full_popup_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/composing_area_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/composing_area_bg.9.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/composing_area_cursor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/composing_area_cursor.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/composing_hl_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/composing_hl_bg.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/delete_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/delete_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/delete_popup_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/delete_popup_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/dun_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/dun_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/dun_popup_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/dun_popup_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_00.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_00_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_00_popup.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_01.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_01_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_01_popup.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_02.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_02_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_02_popup.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_03.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_03_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_03_popup.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_04.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_04_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_04_popup.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_05.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_05_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_05_popup.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_06.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_06_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_06_popup.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_10.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_10_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_10_popup.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_11.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_11_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_11_popup.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_12.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_12_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_12_popup.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_13.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_13_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_13_popup.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_14.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_14_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_14_popup.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_15.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_15_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_15_popup.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_16.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_16_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_16_popup.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_20.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_20_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_20_popup.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_21.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_21_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_21_popup.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_22.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_22_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_22_popup.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_23.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_23_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_23_popup.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_24.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/emotion_icon_24_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/emotion_icon_24_popup.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/enter_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/enter_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/enter_popup_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/enter_popup_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/ime_en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/ime_en.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/ime_pinyin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/ime_pinyin.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/key_balloon_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/key_balloon_bg.9.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/light_key_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/light_key_bg.9.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/light_key_hl_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/light_key_hl_bg.9.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/light_key_up_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/light_key_up_bg.9.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/light_key_up_hl_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/light_key_up_hl_bg.9.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/miniskb_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/miniskb_bg.9.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/normal_key_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/normal_key_bg.9.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/normal_key_hl_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/normal_key_hl_bg.9.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/num0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/num0.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/num1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/num1.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/num2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/num2.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/num3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/num3.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/num4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/num4.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/num5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/num5.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/num6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/num6.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/num7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/num7.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/num8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/num8.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/num9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/num9.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/numalt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/numalt.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/numpound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/numpound.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/numstar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/numstar.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/period_full_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/period_full_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/period_full_popup_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/period_full_popup_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/period_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/period_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/period_popup_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/period_popup_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/search_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/search_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/search_popup_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/search_popup_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/shift_off_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/shift_off_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/shift_off_popup_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/shift_off_popup_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/shift_on_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/shift_on_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/shift_on_popup_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/shift_on_popup_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/skb_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/skb_bg.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/skb_container_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/skb_container_bg.9.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/smiley_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/smiley_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/smiley_popup_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/smiley_popup_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/space_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/space_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/drawable/space_popup_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/drawable/space_popup_icon.png -------------------------------------------------------------------------------- /PinyinIME/src/main/res/layout/candidates_container.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 22 | 23 | 30 | 31 | 38 | 39 | 44 | 48 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /PinyinIME/src/main/res/layout/floating_container.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 21 | 22 | 27 | 28 | -------------------------------------------------------------------------------- /PinyinIME/src/main/res/layout/skb_container.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 21 | 22 | 27 | 28 | 32 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /PinyinIME/src/main/res/raw/dict_pinyin.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/PinyinIME/src/main/res/raw/dict_pinyin.dat -------------------------------------------------------------------------------- /PinyinIME/src/main/res/values-land/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 10dip 18 | 16dip 19 | 20 | -------------------------------------------------------------------------------- /PinyinIME/src/main/res/values-port/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 3dip 18 | 18dip 19 | 20 | -------------------------------------------------------------------------------- /PinyinIME/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | #ffffffff 18 | #ffffffff 19 | #ff000000 20 | #ff000000 21 | #ff000000 22 | #ffe35900 23 | #ff343233 24 | #ff000000 25 | #ffffffff 26 | #ff777777 27 | 28 | -------------------------------------------------------------------------------- /PinyinIME/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 0dip 18 | 19 | -------------------------------------------------------------------------------- /PinyinIME/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 谷歌拼音输入法 18 | 谷歌拼音输入法设置 19 | 20 | 1.0.0 21 | 22 | 23 | 0 24 | 1 25 | 2 26 | 3 27 | 4 28 | 5 29 | 6 30 | 7 31 | 8 32 | 9 33 | 10 34 | 11 35 | 12 36 | 13 37 | 14 38 | 15 39 | 3 40 | 41 | 42 | setting_sound_key 43 | setting_vibrate_key 44 | setting_prediction_key 45 | setting_switch_key 46 | setting_advanced_key 47 | 48 | 谷歌拼音输入法设置 49 | 按键声音 50 | 按键震动 51 | 联想输入 52 | 中英文切换 53 | Shift-space 54 | 55 | 开启 56 | 关闭 57 | 58 | 其它设置 59 | 词典同步等 60 | 61 | 62 | -------------------------------------------------------------------------------- /PinyinIME/src/main/res/xml/settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 19 | 20 | 26 | 27 | 33 | 34 | 40 | 41 | 42 | 46 | 47 | 48 | 49 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /PinyinIME/src/main/res/xml/skb_phone.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | icon="@drawable/numpound"/> 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /PinyinIME/src/main/res/xml/skb_sym1.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 24 | 25 | 26 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 80 | 82 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /PinyinIME/src/main/res/xml/skb_sym2.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tessercube 2 | OpenPGP Made Mobile 3 | 4 | [Get it on F-Droid](https://f-droid.org/packages/com.dimension.tessercube/) 7 | [Get it on Google Play](https://play.google.com/store/apps/details?id=com.dimension.tessercube) 10 | 11 | # Fully OpenPGP 12 | Tessercube abides to common standards of OpenPGP. 13 | 14 | # Encryption Made Everywhere 15 | Use OpenPGP in any app with Tessercube keyboard. 16 | 17 | # Messages Made Trackable 18 | Never fail finding previous messages. 19 | 20 | # How to build 21 | Requirement: 22 | - ndk-r19c 23 | - android-28 24 | - Kotlin plugin (When using Android Studio) 25 | 26 | Clone the project 27 | ``` 28 | git clone https://github.com/DimensionDev/Tessercube-Android.git 29 | ``` 30 | We're using a modified version of LatinIME as a submodule, so we need to initial the submodules 31 | ``` 32 | git submodule update --init --recursive 33 | ``` 34 | You can run a debug build using 35 | ``` 36 | ./gradlew assembleDebug 37 | ``` 38 | 39 | # Dependency 40 | - Kotlin 41 | - AndroidX 42 | - [LatinIME](https://android.googlesource.com/platform/packages/inputmethods/LatinIME/) 43 | - [PinyinIME](https://android.googlesource.com/platform/packages/inputmethods/PinyinIME/) 44 | - [inputmethodcommon](https://android.googlesource.com/platform/frameworks/opt/inputmethodcommon/) 45 | - [Dexter](https://github.com/Karumi/Dexter) 46 | - [RxJava](https://github.com/ReactiveX/RxJava) 47 | - [MaterialTapTargetPrompt](https://github.com/sjwall/MaterialTapTargetPrompt) 48 | - [chips-input-layout](https://github.com/tylersuehr7/chips-input-layout) 49 | - [prettytime](https://github.com/ocpsoft/prettytime) 50 | - [FloatingHover](https://github.com/Tlaster/FloatingHover) 51 | - [KotlinPGP](https://github.com/Tlaster/KotlinPGP) 52 | - [PageIndicatorView](https://github.com/romandanylyk/PageIndicatorView) 53 | - [leakcanary](https://github.com/square/leakcanary) 54 | - [glide](https://github.com/bumptech/glide) 55 | - [requery](https://github.com/requery/requery) 56 | - [BouncyCastle](https://github.com/bcgit/bc-java) 57 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | 3 | android { 4 | compileSdkVersion target_version 5 | aaptOptions { 6 | noCompress 'dat' 7 | } 8 | defaultConfig { 9 | applicationId app_id 10 | minSdkVersion min_version 11 | targetSdkVersion target_version 12 | versionCode 326 13 | versionName '0.5.1' 14 | } 15 | 16 | signingConfigs { 17 | release { 18 | storeFile file(signConfig['keyStore']) 19 | storePassword signConfig['keyStorePassword'] 20 | keyAlias signConfig['keyAlias'] 21 | keyPassword signConfig['keyPassword'] 22 | } 23 | } 24 | 25 | buildTypes { 26 | release { 27 | signingConfig signingConfigs.release 28 | minifyEnabled false 29 | proguardFiles getDefaultProguardFile('proguard-android.txt') 30 | } 31 | } 32 | 33 | sourceSets { 34 | main { 35 | manifest.srcFile '../LatinIME/java/AndroidManifest.xml' 36 | java.srcDirs = ['../LatinIME/java/src', '../LatinIME/common/src', '../LatinIME/java-overridable/src', '../inputmethodcommon/java'] 37 | res.srcDirs = ['../LatinIME/java/res', '../LatinIME/java-overridable/res'] 38 | } 39 | } 40 | 41 | externalNativeBuild { 42 | ndkBuild { 43 | path "../LatinIME/native/jni/Android.mk" 44 | } 45 | } 46 | 47 | lintOptions { 48 | abortOnError false 49 | checkReleaseBuilds false 50 | } 51 | 52 | defaultConfig { 53 | externalNativeBuild { 54 | ndkBuild { 55 | // Suppress build failing warnings from dependencies 56 | cFlags "-w" 57 | arguments "TARGET_BUILD_APPS=true" 58 | } 59 | } 60 | } 61 | compileOptions { 62 | sourceCompatibility 1.8 63 | targetCompatibility 1.8 64 | } 65 | } 66 | 67 | dependencies { 68 | implementation 'com.google.code.findbugs:jsr305:3.0.2' 69 | implementation 'androidx.legacy:legacy-support-v4:1.0.0' 70 | implementation project(':tessercubecore') 71 | implementation project(':PinyinIME') 72 | } 73 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | image: Ubuntu1804 2 | environment: 3 | ANDROID_COMPILE_SDK: "28" 4 | ANDROID_SDK_TOOLS: "28.0.3" 5 | ANDROID_SDK_VERSION: "4333796" 6 | ANDROID_NDK_VERSION: "18b" 7 | GIT_SUBMODULE_STRATEGY: recursive 8 | JAVA_HOME: /usr/lib/jvm/java-8-openjdk-amd64 9 | 10 | build_script: 11 | - which java && which javac && java -version 12 | - echo java home is $JAVA_HOME 13 | - git submodule update --init --recursive 14 | - sudo apt update && sudo apt install -y curl bsdtar make file && sudo rm -rf /var/lib/apt/lists/* 15 | - sudo mkdir -p $PWD/android-sdk 16 | - sudo curl https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_VERSION}.zip | sudo bsdtar -xpf- -C $PWD/android-sdk 17 | - export ANDROID_SDK_HOME="$PWD/android-sdk" 18 | - export ANDROID_HOME="$ANDROID_SDK_HOME" 19 | - export NDK_HOME="$ANDROID_SDK_HOME/ndk-bundle" 20 | - export ANDROID_NDK="$NDK_HOME" 21 | - export ANDROID_NDK_HOME="$NDK_HOME" 22 | - export ANDROID_NDK_ROOT="$NDK_HOME" 23 | - export PATH="${ANDROID_SDK_HOME}/tools/bin:${ANDROID_SDK_HOME}/platform-tools:${ANDROID_NDK_HOME}:${PATH}" 24 | - sudo chmod -R 777 ${ANDROID_HOME} 25 | - unset JAVA_TOOL_OPTIONS 26 | - echo y | sdkmanager "ndk-bundle" "build-tools;${ANDROID_SDK_TOOLS}" "platform-tools" "platforms;android-${ANDROID_COMPILE_SDK}" 27 | - chmod +x ./gradlew 28 | - ./gradlew assembleDebug 29 | 30 | artifacts: 31 | - path: '**\*.apk' 32 | name: apk -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.61' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.5.3' 9 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 10 | } 11 | } 12 | 13 | allprojects { 14 | repositories { 15 | google() 16 | mavenCentral() 17 | jcenter() 18 | maven { url 'https://jitpack.io' } 19 | } 20 | } 21 | 22 | subprojects { 23 | buildscript { 24 | ext { 25 | app_id = 'com.dimension.tessercube' 26 | min_version = 21 27 | target_version = 29 28 | version_code = 1 29 | version_name = '1.0' 30 | appcenter = [ 31 | enabled : project.hasProperty('appCenterEnabled') ? appCenterEnabled : 'false', 32 | id : project.hasProperty('appCenterId') ? appCenterId : '' 33 | ] 34 | signConfig = [ 35 | keyStore : project.hasProperty('signKeyStore') ? signKeyStore : './key.jks', 36 | keyStorePassword : project.hasProperty('signKeyStorePassword') ? signKeyStorePassword : 'password', 37 | keyAlias : project.hasProperty('signKeyAlias') ? signKeyAlias : 'alias', 38 | keyPassword : project.hasProperty('signKeyPassword') ? signKeyPassword : 'password' 39 | ] 40 | dependencyVersion = [ 41 | appCenter : "1.11.4", 42 | requery : "1.5.1", 43 | glide : "4.10.0", 44 | leakcanary : "2.0", 45 | bouncycastle : '1.62' 46 | ] 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | android.enableJetifier=true 2 | android.useAndroidX=true 3 | org.gradle.jvmargs=-Xmx1536m 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionSha256Sum=14cd15fc8cc8705bd69dcfa3c8fefb27eb7027f5de4b47a8b279218f76895a91 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /metadata/com.dimension.tessercube.yml: -------------------------------------------------------------------------------- 1 | 2 | Name: Tessercube 3 | 4 | # Categories (one per line, each starting with a space and a minus), chosen from the 5 | # official list: https://gitlab.com/fdroid/fdroiddata/blob/master/stats/categories.txt 6 | Categories: Security 7 | 8 | # the one license that the whole app is available under, use 9 | # https://spdx.org/licenses/ short identifiers, must be 10 | # floss-compatible. 11 | License: AGPL-3.0 12 | 13 | # A URL for the project's website 14 | WebSite: https://tessercube.com/ 15 | 16 | # A link to the issue tracker where bugs are reported 17 | IssueTracker: https://github.com/DimensionDev/Tessercube-Android/issues 18 | 19 | # One sentence, no more than 30-50 chars, no trailing punctuation, 20 | # focus on actions what the users does with the app, e.g. "Read and 21 | # send emails" instead of "Email client". 22 | Summary: OpenPGP Made Mobile 23 | Description: | 24 | OpenPGP Made Mobile 25 | 26 | # git, git-svn, svn, hg or bzr 27 | RepoType: git 28 | 29 | # source code repo URL (HTTPS required) 30 | Repo: https://github.com/DimensionDev/Tessercube-Android.git 31 | 32 | Builds: 33 | - versionName: '1.0' 34 | versionCode: 1 35 | commit: 0.2.5 36 | subdir: app 37 | gradle: 38 | - yes 39 | 40 | AutoUpdateMode: Version %v 41 | UpdateCheckMode: Tags -------------------------------------------------------------------------------- /privacy_policy.md: -------------------------------------------------------------------------------- 1 | ## General information 2 | 3 | This Privacy Policy is provided to help you understand how we collect, use and disclose information, 4 | including personal information that you may provide to us or that we may obtain as Tessercube is used. 5 | Please read this carefully before using Tessercube and its services operated by us. 6 | We may update this Privacy Policy from time to time, so please check back with us periodically. 7 | "Personal Information" includes information that alone or when in combination with other information 8 | may be used to readily identify, contact, or locate you or a specific individual. 9 | 10 | ## Collected information and usage 11 | By using Tessercube, you consent to restore or create a new key pair in the app. All the "Personal Information" will be stored 12 | securely in the system and will never be collected and sent to our server. Typing behavior will not be tracked at this moment 13 | but in order to provide a better service in the future, we may add this feature to learn and help you type faster and more accurate. 14 | 15 | Your contacts list is read to help you find target contact easily. You may disable this feature in the setting pages. 16 | 17 | ## When Tessercube may share collected information 18 | Never. We don't even collect information. 19 | 20 | ## Changes to this privacy policy by Tessercube 21 | If in the future we change our Privacy Policy, we will post the new Privacy Policy on this Website and Application 22 | (as as app update). We reserve the right to change this Privacy Policy in the future. 23 | Your continued use of Tessercube following a change in the Privacy Policy represents 24 | consent to the new Privacy Policy to the fullest extent permitted by law. 25 | We encourage you to periodically review this Privacy Policy. 26 | 27 | ## Contacting Tessercube 28 | If you have any questions, comments, or concerns about this Privacy Policy, please email us at info@tessercube.com 29 | or visit tessercube.com 30 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':tessercubecore', ':PinyinIME' 2 | rootProject.name = "Tessercube" 3 | 4 | -------------------------------------------------------------------------------- /tessercubecore/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | .kotlintest -------------------------------------------------------------------------------- /tessercubecore/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -keep public class * implements com.bumptech.glide.module.GlideModule 23 | -keep public class * extends com.bumptech.glide.module.AppGlideModule 24 | -keep public enum com.bumptech.glide.load.ImageHeaderParser$** { 25 | **[] $VALUES; 26 | public *; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /tessercubecore/src/androidTest/java/com/sujitech/tessercubecore/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore 2 | 3 | 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey 6 | import org.bouncycastle.jce.provider.BouncyCastleProvider 7 | import org.junit.Test 8 | import org.junit.runner.RunWith 9 | import java.security.KeyPairGenerator 10 | import java.security.Security 11 | import java.security.interfaces.ECPublicKey 12 | import java.security.spec.ECGenParameterSpec 13 | 14 | 15 | /** 16 | * Instrumented test, which will execute on an Android device. 17 | * 18 | * @see [Testing documentation](http://d.android.com/tools/testing) 19 | */ 20 | @RunWith(AndroidJUnit4::class) 21 | class ExampleInstrumentedTest { 22 | @Test 23 | fun useAppContext() { 24 | Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME) 25 | Security.insertProviderAt(BouncyCastleProvider(), 1) 26 | val g = KeyPairGenerator.getInstance("EC") 27 | val kpgparams = ECGenParameterSpec("secp256k1") 28 | g.initialize(kpgparams) 29 | val pair = g.generateKeyPair() 30 | println((pair.private as BCECPrivateKey).s.toString(16)) 31 | (pair.public as ECPublicKey).w 32 | //// val a = getPublicKeyDetails(pair.public as BCECPublicKey) 33 | // val field = pair.public.javaClass.superclass.getDeclaredField("key") 34 | // field.isAccessible = true 35 | // val key = field.get(pair.public) as ByteArray 36 | // println(key.toHexString()) 37 | // println(pair.public as ECPublicKey) 38 | // println(pair.public.encoded.toHexString()) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tessercubecore/src/main/ic_launcher_tessercube-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/tessercubecore/src/main/ic_launcher_tessercube-web.png -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/activity/BaseActivity.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.activity 2 | 3 | import android.os.Bundle 4 | import android.view.MenuItem 5 | import androidx.appcompat.app.AppCompatActivity 6 | import androidx.appcompat.widget.Toolbar 7 | import com.sujitech.tessercubecore.R 8 | 9 | 10 | abstract class BaseActivity: AppCompatActivity() { 11 | 12 | override fun onPostCreate(savedInstanceState: Bundle?) { 13 | super.onPostCreate(savedInstanceState) 14 | val toolbar = findViewById(R.id.toolbar) 15 | if (toolbar != null) { 16 | setSupportActionBar(toolbar) 17 | } 18 | } 19 | 20 | override fun onOptionsItemSelected(item: MenuItem?): Boolean { 21 | if (item != null && item.itemId == android.R.id.home) { 22 | onBackPressed() 23 | } 24 | return super.onOptionsItemSelected(item) 25 | } 26 | 27 | override fun onDestroy() { 28 | super.onDestroy() 29 | onDestroyCallback?.invoke() 30 | } 31 | 32 | public var onDestroyCallback: (() -> Unit)? = null 33 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/activity/SplashActivity.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.activity 2 | 3 | import android.os.Bundle 4 | import com.sujitech.tessercubecore.common.Settings 5 | import com.sujitech.tessercubecore.common.extension.toActivity 6 | 7 | class SplashActivity : BaseActivity() { 8 | 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | if (Settings.get("is_first_run", true)) { 12 | Settings.set("is_first_run", false) 13 | toActivity() 14 | } else { 15 | toActivity() 16 | } 17 | finish() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/activity/TutorialActivity.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.activity 2 | 3 | import android.os.Bundle 4 | import androidx.core.view.isVisible 5 | import androidx.transition.TransitionManager 6 | import androidx.viewpager.widget.ViewPager 7 | import com.sujitech.tessercubecore.R 8 | import com.sujitech.tessercubecore.common.adapter.ChildViewAdapter 9 | import com.sujitech.tessercubecore.common.extension.toActivity 10 | import kotlinx.android.synthetic.main.activity_tutorial.* 11 | 12 | class TutorialActivity : BaseActivity() { 13 | 14 | override fun onCreate(savedInstanceState: Bundle?) { 15 | super.onCreate(savedInstanceState) 16 | setContentView(R.layout.activity_tutorial) 17 | viewPager.adapter = ChildViewAdapter(viewPager) 18 | viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { 19 | override fun onPageScrollStateChanged(state: Int) { 20 | } 21 | 22 | override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { 23 | } 24 | 25 | override fun onPageSelected(position: Int) { 26 | TransitionManager.beginDelayedTransition(root) 27 | next_button.isVisible = position != viewPager.childCount - 1 28 | confirm_button.isVisible = position == viewPager.childCount - 1 29 | } 30 | }) 31 | next_button.setOnClickListener { 32 | viewPager.currentItem++ 33 | } 34 | confirm_button.setOnClickListener { 35 | toActivity() 36 | finish() 37 | } 38 | skip_button.setOnClickListener { 39 | toActivity() 40 | finish() 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/activity/contact/EditContactActivity.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.activity.contact 2 | 3 | import android.os.Bundle 4 | import android.view.Menu 5 | import android.view.MenuItem 6 | import android.widget.ArrayAdapter 7 | import com.sujitech.tessercubecore.R 8 | import com.sujitech.tessercubecore.activity.BaseActivity 9 | import com.sujitech.tessercubecore.data.ContactDataEntity 10 | import com.sujitech.tessercubecore.data.DbContext 11 | import com.sujitech.tessercubecore.data.TrustLevel 12 | import kotlinx.android.synthetic.main.activity_edit_contact.* 13 | 14 | 15 | 16 | 17 | class EditContactActivity : BaseActivity() { 18 | 19 | private val data: ContactDataEntity by lazy { 20 | intent.getParcelableExtra("data") 21 | } 22 | 23 | 24 | override fun onCreate(savedInstanceState: Bundle?) { 25 | super.onCreate(savedInstanceState) 26 | setContentView(R.layout.activity_edit_contact) 27 | update_from_server_button.setOnClickListener { 28 | 29 | } 30 | delete_contact_button.setOnClickListener { 31 | DbContext.data.delete(data).blockingGet() 32 | finish() 33 | } 34 | name_input.setText(data.name) 35 | mail_input.setText(data.email) 36 | trust_level_spinner.adapter = ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, TrustLevel.values()) 37 | trust_level_spinner.post { 38 | trust_level_spinner.setSelection(TrustLevel.values().indexOf(data.trustLevel)) 39 | } 40 | } 41 | 42 | override fun onOptionsItemSelected(item: MenuItem?): Boolean { 43 | if (item != null && item.itemId == R.id.menu_done) { 44 | data.name = name_input.text.toString() 45 | data.email = mail_input.text.toString() 46 | data.trustLevel = trust_level_spinner.selectedItem as TrustLevel 47 | DbContext.data.update(data).blockingGet() 48 | finish() 49 | } 50 | return super.onOptionsItemSelected(item) 51 | } 52 | 53 | override fun onCreateOptionsMenu(menu: Menu): Boolean { 54 | val inflater = menuInflater 55 | inflater.inflate(R.menu.edit_contact_toolbar, menu) 56 | return super.onCreateOptionsMenu(menu) 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/activity/keypair/ImportKeyActivity.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.activity.keypair 2 | 3 | import android.os.Bundle 4 | import com.sujitech.tessercubecore.R 5 | import com.sujitech.tessercubecore.activity.BaseActivity 6 | import com.sujitech.tessercubecore.common.extension.toActivity 7 | import kotlinx.android.synthetic.main.activity_import_key.* 8 | 9 | class ImportKeyActivity : BaseActivity() { 10 | 11 | override fun onCreate(savedInstanceState: Bundle?) { 12 | super.onCreate(savedInstanceState) 13 | setContentView(R.layout.activity_import_key) 14 | cancel_button.setOnClickListener { 15 | finish() 16 | } 17 | paste_private_key_button.setOnClickListener { 18 | toActivity() 19 | finish() 20 | } 21 | scan_qr_code_button.setOnClickListener { 22 | 23 | } 24 | mnemonic_words_button.setOnClickListener { 25 | 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/common/Config.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.common 2 | 3 | import com.sujitech.tessercubecore.BuildConfig 4 | -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/common/Constants.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.common 2 | 3 | import org.ocpsoft.prettytime.PrettyTime 4 | 5 | val prettyTime by lazy { 6 | PrettyTime() 7 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/common/DataTracking.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.common 2 | 3 | import android.app.Application 4 | 5 | object DataTracking { 6 | fun init(app: Application) { 7 | // Do nothing 8 | } 9 | fun track(name: String, data: Map) { 10 | // Do nothing 11 | } 12 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/common/FloatingHoverUtils.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.common 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.net.Uri 6 | import android.os.Build 7 | import android.provider.Settings 8 | 9 | object FloatingHoverUtils { 10 | fun hasPermission(context: Context): Boolean { 11 | return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Settings.canDrawOverlays(context) 12 | } 13 | 14 | fun checkPermission(context: Context) { 15 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 16 | if (!hasPermission(context)) { 17 | val intent = Intent( 18 | Settings.ACTION_MANAGE_OVERLAY_PERMISSION, 19 | Uri.parse("package:${context.packageName}") 20 | ) 21 | context.startActivity(intent) 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/common/IMEUtils.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.common 2 | 3 | import android.content.Context 4 | import android.provider.Settings 5 | import android.view.inputmethod.InputMethodInfo 6 | import android.view.inputmethod.InputMethodManager 7 | 8 | object IMEUtils { 9 | fun isThisImeEnabled(context: Context, imm: InputMethodManager): Boolean { 10 | val packageName = context.packageName 11 | for (imi in imm.enabledInputMethodList) { 12 | if (packageName == imi.packageName) { 13 | return true 14 | } 15 | } 16 | return false 17 | } 18 | 19 | fun isThisImeCurrent(context: Context, imm: InputMethodManager): Boolean { 20 | val imi = getInputMethodInfoOf(context.packageName, imm) 21 | val currentImeId = Settings.Secure.getString( 22 | context.contentResolver, Settings.Secure.DEFAULT_INPUT_METHOD) 23 | return imi != null && imi.id == currentImeId 24 | } 25 | 26 | private fun getInputMethodInfoOf(packageName: String, imm: InputMethodManager): InputMethodInfo? { 27 | for (imi in imm.inputMethodList) { 28 | if (packageName == imi.packageName) { 29 | return imi 30 | } 31 | } 32 | return null 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/common/OpenPGPUtils.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.common 2 | 3 | import android.graphics.Color 4 | import moe.tlaster.kotlinpgp.data.VerifyStatus 5 | 6 | fun VerifyStatus.toColor(): Int { 7 | return when (this) { 8 | VerifyStatus.NO_SIGNATURE -> Color.TRANSPARENT 9 | VerifyStatus.SIGNATURE_BAD -> Color.RED 10 | VerifyStatus.SIGNATURE_OK -> Color.GREEN 11 | VerifyStatus.UNKNOWN_PUBLIC_KEY -> Color.YELLOW 12 | } 13 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/common/Settings.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.common 2 | 3 | import android.content.Context 4 | import android.content.SharedPreferences 5 | import com.sujitech.tessercubecore.appContext 6 | 7 | object Settings { 8 | val preferences: SharedPreferences by lazy { 9 | appContext.getSharedPreferences("tessercube", Context.MODE_PRIVATE) 10 | } 11 | inline fun get(key: String, defaultValue: T): T { 12 | return when (defaultValue) { 13 | is String -> preferences.getString(key, defaultValue) as T 14 | is Boolean -> preferences.getBoolean(key, defaultValue) as T 15 | is Long -> preferences.getLong(key, defaultValue) as T 16 | is Float -> preferences.getFloat(key, defaultValue) as T 17 | is Double -> preferences.getFloat(key, defaultValue.toFloat()).toDouble() as T 18 | is Int -> preferences.getInt(key, defaultValue) as T 19 | else -> return defaultValue 20 | } 21 | } 22 | inline fun set(key: String, value: T) { 23 | preferences.edit().also { 24 | when (value) { 25 | is String -> it.putString(key, value) 26 | is Boolean -> it.putBoolean(key, value) 27 | is Long -> it.putLong(key, value) 28 | is Float -> it.putFloat(key, value) 29 | is Double -> it.putFloat(key, value.toFloat()) 30 | is Int -> it.putInt(key, value) 31 | } 32 | }.apply() 33 | } 34 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/common/UserPasswordStorage.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.common 2 | 3 | import android.accounts.Account 4 | import android.accounts.AccountManager 5 | import android.content.Context 6 | 7 | 8 | object UserPasswordStorage { 9 | fun save(context: Context, id: String, password: String): Boolean { 10 | val accountManager = AccountManager.get(context) 11 | val account = Account(id, context.packageName) 12 | return accountManager.addAccountExplicitly(account, password, null) 13 | } 14 | 15 | fun get(context: Context, id: String): String? { 16 | val accountManager = AccountManager.get(context) 17 | val account = accountManager.accounts.firstOrNull { 18 | it.name == id 19 | } 20 | return if (account != null) { 21 | accountManager.getPassword(account) 22 | } else { 23 | null 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/common/adapter/ChildViewAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.common.adapter 2 | 3 | import android.view.View 4 | import android.view.ViewGroup 5 | import androidx.viewpager.widget.PagerAdapter 6 | import androidx.viewpager.widget.ViewPager 7 | 8 | class ChildViewAdapter(private val viewPager: ViewPager) : PagerAdapter() { 9 | init { 10 | viewPager.offscreenPageLimit = viewPager.childCount 11 | } 12 | 13 | override fun instantiateItem(container: ViewGroup, position: Int): Any { 14 | return viewPager.getChildAt(position) 15 | } 16 | 17 | override fun isViewFromObject(view: View, `object`: Any): Boolean { 18 | return view === `object` as View 19 | } 20 | 21 | override fun getCount(): Int { 22 | return viewPager.childCount 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/common/adapter/FragmentAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.common.adapter 2 | 3 | import androidx.fragment.app.Fragment 4 | import androidx.fragment.app.FragmentManager 5 | import androidx.fragment.app.FragmentPagerAdapter 6 | 7 | 8 | class FragmentAdapter(val list: List, fm: FragmentManager) : FragmentPagerAdapter(fm) { 9 | override fun getItem(position: Int): Fragment = list[position] 10 | override fun getCount(): Int = list.size 11 | } 12 | 13 | -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/common/collection/CollectionChangedEventArg.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.common.collection 2 | 3 | class CollectionChangedEventArg( 4 | val type: CollectionChangedType, 5 | val index: Int = -1, 6 | val count: Int = 1 7 | ) -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/common/collection/CollectionChangedType.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.common.collection 2 | 3 | enum class CollectionChangedType { 4 | Add, 5 | Remove, 6 | Update, 7 | Reset, 8 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/common/collection/IIncrementalSource.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.common.collection 2 | 3 | interface IIncrementalSource { 4 | suspend fun getPagedItemAsync(page: Int, count: Int): List 5 | } 6 | 7 | interface ICachedIncrementalSource: IIncrementalSource { 8 | suspend fun getCachedItemsAsync(): List 9 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/common/collection/ISupportIncrementalLoading.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.common.collection 2 | 3 | import kotlinx.coroutines.CoroutineScope 4 | 5 | interface ISupportIncrementalLoading { 6 | suspend fun loadMoreItemsAsync() 7 | val hasMoreItems: Boolean 8 | val scope: CoroutineScope 9 | } 10 | 11 | interface ISupportCacheLoading { 12 | suspend fun loadCachedAsync() 13 | val scope: CoroutineScope 14 | } 15 | 16 | -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/common/collection/IncrementalLoadingCollection.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.common.collection 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import kotlinx.coroutines.CoroutineScope 5 | import kotlinx.coroutines.GlobalScope 6 | import kotlinx.coroutines.launch 7 | 8 | open class IncrementalLoadingCollection, T>( 9 | private val source: TSource, 10 | private val itemsPerPage: Int = 20, 11 | override val scope: CoroutineScope = GlobalScope 12 | ): ObservableCollection(), ISupportIncrementalLoading, ISupportCacheLoading { 13 | 14 | val onError = MutableLiveData() 15 | 16 | enum class CollectionState { 17 | Loading, 18 | Completed 19 | } 20 | 21 | protected var currentPageIndex = 0 22 | val stateChanged = MutableLiveData() 23 | var isLoading = false 24 | 25 | fun refresh() { 26 | scope.launch { 27 | refreshAsync() 28 | } 29 | } 30 | 31 | suspend fun refreshAsync() { 32 | currentPageIndex = 0 33 | hasMoreItems = true 34 | loadMoreItemsAsync() 35 | } 36 | 37 | override suspend fun loadMoreItemsAsync() { 38 | if (isLoading) { 39 | return 40 | } 41 | isLoading = true 42 | stateChanged.value = CollectionState.Loading 43 | var result: List? = null 44 | val lazyClear = currentPageIndex == 0 45 | try { 46 | result = source.getPagedItemAsync(currentPageIndex++, itemsPerPage) 47 | } catch (e: Throwable) { 48 | onError. value = e 49 | e.printStackTrace() 50 | } 51 | if (lazyClear) { 52 | clear() 53 | } 54 | if (result != null && result.any()) { 55 | addAll(result) 56 | } else { 57 | hasMoreItems = false 58 | } 59 | stateChanged.value = CollectionState.Completed 60 | isLoading = false 61 | } 62 | 63 | override suspend fun loadCachedAsync() { 64 | if (source !is ICachedIncrementalSource<*>) { 65 | return 66 | } 67 | if (isLoading) { 68 | return 69 | } 70 | isLoading = true 71 | stateChanged.value = CollectionState.Loading 72 | kotlin.runCatching { 73 | source.getCachedItemsAsync() 74 | }.onFailure { 75 | onError.value = it 76 | it.printStackTrace() 77 | }.onSuccess { 78 | addAll(it.map { it as T }) 79 | } 80 | stateChanged.value = CollectionState.Completed 81 | isLoading = false 82 | } 83 | 84 | override var hasMoreItems: Boolean = true 85 | } 86 | -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/common/extension/Biometric.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.common.extension 2 | 3 | import android.content.Context 4 | import androidx.biometric.BiometricManager 5 | import androidx.biometric.BiometricPrompt 6 | import androidx.core.content.ContextCompat 7 | import androidx.fragment.app.Fragment 8 | import androidx.fragment.app.FragmentActivity 9 | import kotlinx.coroutines.coroutineScope 10 | import kotlin.coroutines.resume 11 | import kotlin.coroutines.suspendCoroutine 12 | 13 | suspend fun FragmentActivity.biometricAuthentication( 14 | title: String, 15 | subTitle: String, 16 | confirmRequired: Boolean = false 17 | ) = suspendCoroutine { 18 | val biometricManager = BiometricManager.from(this) 19 | if (biometricManager.canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS){ 20 | val executor = ContextCompat.getMainExecutor(this) 21 | val callback = object: BiometricPrompt.AuthenticationCallback() { 22 | override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { 23 | it.resume(false) 24 | } 25 | 26 | override fun onAuthenticationFailed() { 27 | it.resume(false) 28 | } 29 | 30 | override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { 31 | it.resume(true) 32 | } 33 | } 34 | val biometricPrompt = BiometricPrompt(this, executor, callback) 35 | val promptInfo = BiometricPrompt.PromptInfo.Builder() 36 | .setTitle(title) 37 | .setSubtitle(subTitle) 38 | .setNegativeButtonText("Cancel") 39 | // DeviceCredential will trigger onAuthenticationError 40 | // .setDeviceCredentialAllowed(true) 41 | .setConfirmationRequired(confirmRequired) 42 | .build() 43 | biometricPrompt.authenticate(promptInfo) 44 | } else { 45 | it.resume(true) 46 | } 47 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/common/extension/HexExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.common.extension 2 | 3 | import kotlin.math.absoluteValue 4 | 5 | fun String.toFormattedHexText(): String { 6 | return toUpperCase().chunked(4).joinToString(" ") 7 | } 8 | 9 | fun String.splitTo(numberEachLine: Int): String { 10 | return split(" ").chunked(numberEachLine).map { it.joinToString(" ") }.joinToString(System.lineSeparator()) 11 | } 12 | 13 | fun Long.toFormattedHexText(): String { 14 | return absoluteValue.toString(16).toFormattedHexText() 15 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/common/extension/ImageExtension.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.common.extension 2 | 3 | import android.graphics.Bitmap 4 | import android.graphics.drawable.Drawable 5 | import android.widget.ImageView 6 | import androidx.annotation.DrawableRes 7 | import com.bumptech.glide.Glide 8 | import java.io.File 9 | 10 | fun ImageView.load(path: String) { 11 | Glide.with(this).load(path).centerCrop().into(this) 12 | } 13 | fun ImageView.load(bitmap: Bitmap) { 14 | Glide.with(this).load(bitmap).centerCrop().into(this) 15 | } 16 | fun ImageView.load(drawable: Drawable) { 17 | Glide.with(this).load(drawable).centerCrop().into(this) 18 | } 19 | fun ImageView.load(@DrawableRes id: Int) { 20 | Glide.with(this).load(id).centerCrop().into(this) 21 | } 22 | fun ImageView.load(file: File) { 23 | Glide.with(this).load(file).centerCrop().into(this) 24 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/common/extension/pgpContentExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.common.extension 2 | 3 | // 4 | //val String.isPGPMessage 5 | // get() = 6 | // (this.startsWith(appContext.getString(R.string.pgp_message_start)) 7 | // && this.endsWith(appContext.getString(R.string.pgp_message_end))) 8 | // || (this.startsWith(appContext.getString(R.string.pgp_signed_message_start)) 9 | // && this.endsWith(appContext.getString(R.string.pgp_signed_message_end))) 10 | // 11 | // 12 | //val String.isPGPPublicKey 13 | // get() = this.startsWith(appContext.getString(R.string.pgp_public_key_start)) && this.endsWith(appContext.getString(R.string.pgp_public_key_end)) 14 | // 15 | //val String.isPGPPrivateKey 16 | // get() = this.startsWith(appContext.getString(R.string.pgp_private_key_start)) && this.endsWith(appContext.getString(R.string.pgp_private_key_end)) 17 | -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/data/DbContext.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.data 2 | 3 | import com.sujitech.tessercubecore.appContext 4 | import io.requery.Persistable 5 | import io.requery.android.sqlite.DatabaseSource 6 | import io.requery.reactivex.KotlinReactiveEntityStore 7 | import io.requery.sql.KotlinEntityDataStore 8 | 9 | 10 | object DbContext { 11 | 12 | val data: KotlinReactiveEntityStore by lazy { 13 | val source = DatabaseSource(appContext, Models.DEFAULT, 1) 14 | KotlinReactiveEntityStore(KotlinEntityDataStore(source.configuration)) 15 | } 16 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/fragment/ViewPagerFragment.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.fragment 2 | 3 | import android.view.KeyEvent 4 | import androidx.fragment.app.Fragment 5 | 6 | abstract class ViewPagerFragment: Fragment() { 7 | open fun onPageSelected() { 8 | 9 | } 10 | 11 | open fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { 12 | return false 13 | } 14 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/keyboard/KeyboardEncryptButton.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.keyboard 2 | 3 | import android.content.ClipboardManager 4 | import android.content.Context 5 | import android.util.AttributeSet 6 | import android.view.LayoutInflater 7 | import android.widget.FrameLayout 8 | import androidx.core.view.isVisible 9 | import com.sujitech.tessercubecore.R 10 | import com.sujitech.tessercubecore.common.extension.getClipboardText 11 | import kotlinx.android.synthetic.main.widget_keyboard_encrypt_button.view.* 12 | import moe.tlaster.kotlinpgp.isPGPMessage 13 | 14 | class KeyboardEncryptButton : FrameLayout, ClipboardManager.OnPrimaryClipChangedListener { 15 | override fun onPrimaryClipChanged() { 16 | val clip = context.getClipboardText() 17 | button_dot.isVisible = clip.isPGPMessage 18 | } 19 | 20 | constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { 21 | init(context, attrs, 0) 22 | } 23 | 24 | constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) { 25 | init(context, attrs, defStyle) 26 | } 27 | 28 | private fun init(context: Context, attrs: AttributeSet, defStyle: Int) { 29 | LayoutInflater.from(context).inflate(R.layout.widget_keyboard_encrypt_button, this) 30 | button_dot.isVisible = false 31 | // val clipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager 32 | // clipboardManager.addPrimaryClipChangedListener(this) 33 | } 34 | 35 | fun hideDot() { 36 | button_dot.isVisible = false 37 | } 38 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/service/DummyAccountService.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.service 2 | 3 | 4 | import android.accounts.AbstractAccountAuthenticator 5 | import android.accounts.Account 6 | import android.accounts.AccountAuthenticatorResponse 7 | import android.app.Service 8 | import android.content.Intent 9 | import android.os.Bundle 10 | import android.os.IBinder 11 | 12 | class DummyAccountService : Service() { 13 | private inner class Authenticator : AbstractAccountAuthenticator(this@DummyAccountService) { 14 | 15 | override fun editProperties(response: AccountAuthenticatorResponse, accountType: String): Bundle? { 16 | return null 17 | } 18 | 19 | override fun addAccount(response: AccountAuthenticatorResponse, accountType: String, authTokenType: String, 20 | requiredFeatures: Array, options: Bundle): Bundle? { 21 | response.onResult(Bundle()) 22 | return null 23 | } 24 | 25 | override fun confirmCredentials(response: AccountAuthenticatorResponse, account: Account, options: Bundle): Bundle? { 26 | return null 27 | } 28 | 29 | override fun getAuthToken(response: AccountAuthenticatorResponse, account: Account, authTokenType: String, 30 | options: Bundle): Bundle? { 31 | return null 32 | } 33 | 34 | override fun getAuthTokenLabel(authTokenType: String): String? { 35 | return null 36 | } 37 | 38 | override fun updateCredentials(response: AccountAuthenticatorResponse, account: Account, authTokenType: String, 39 | options: Bundle): Bundle? { 40 | return null 41 | } 42 | 43 | override fun hasFeatures(response: AccountAuthenticatorResponse, account: Account, features: Array): Bundle? { 44 | return null 45 | } 46 | } 47 | 48 | override fun onBind(intent: Intent): IBinder { 49 | return Authenticator().iBinder 50 | } 51 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/widget/BlockedViewPager.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.widget 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.MotionEvent 6 | import androidx.viewpager.widget.ViewPager 7 | 8 | class BlockedViewPager(context: Context, attrs: AttributeSet) : ViewPager(context, attrs) { 9 | 10 | var pagingEnabled: Boolean = false 11 | 12 | override fun onTouchEvent(event: MotionEvent): Boolean { 13 | return if (this.pagingEnabled) { 14 | super.onTouchEvent(event) 15 | } else false 16 | 17 | } 18 | 19 | override fun onInterceptTouchEvent(event: MotionEvent): Boolean { 20 | return if (this.pagingEnabled) { 21 | super.onInterceptTouchEvent(event) 22 | } else false 23 | 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/widget/CommandButton.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.widget 2 | 3 | import android.content.Context 4 | import android.graphics.drawable.Drawable 5 | import android.util.AttributeSet 6 | import android.view.LayoutInflater 7 | import android.widget.RelativeLayout 8 | import androidx.core.view.isVisible 9 | import com.sujitech.tessercubecore.R 10 | import kotlinx.android.synthetic.main.widget_command_button.view.* 11 | 12 | class CommandButton : RelativeLayout { 13 | constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { 14 | init(context, attrs, 0) 15 | } 16 | 17 | constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) { 18 | init(context, attrs, defStyle) 19 | } 20 | 21 | private fun init(context: Context, attrs: AttributeSet, defStyle: Int) { 22 | LayoutInflater.from(context).inflate(R.layout.widget_command_button, this) 23 | context.obtainStyledAttributes( 24 | attrs, R.styleable.CommandButton, defStyle, 0).apply { 25 | button_image.setImageDrawable(getDrawable(R.styleable.CommandButton_icon)) 26 | button_text.text = getText(R.styleable.CommandButton_text) 27 | recycle() 28 | } 29 | } 30 | 31 | fun toggle() { 32 | button_text.isVisible = !button_text.isVisible 33 | } 34 | 35 | fun showText() { 36 | button_text.isVisible = true 37 | } 38 | 39 | fun hideText() { 40 | button_text.isVisible = false 41 | } 42 | 43 | var text: CharSequence 44 | get() = button_text.text 45 | set(value) { 46 | button_text.text = value 47 | } 48 | 49 | var icon: Drawable 50 | get() = button_image.drawable 51 | set(value) { 52 | button_image.setImageDrawable(value) 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/widget/ContactView.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.widget 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.LayoutInflater 6 | import androidx.gridlayout.widget.GridLayout 7 | import com.sujitech.tessercubecore.R 8 | import com.sujitech.tessercubecore.common.extension.toFormattedHexText 9 | import com.sujitech.tessercubecore.common.prettyTime 10 | import com.sujitech.tessercubecore.data.ContactData 11 | import kotlinx.android.synthetic.main.widget_contact.view.* 12 | 13 | class ContactView: GridLayout { 14 | constructor(context: Context) : super(context) 15 | constructor(context: Context, attrs: AttributeSet) : super(context, attrs) 16 | constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) 17 | init { 18 | LayoutInflater.from(context).inflate(R.layout.widget_contact, this) 19 | } 20 | 21 | var contact: ContactData? = null 22 | set(value) { 23 | field = value 24 | updateUI(value) 25 | } 26 | 27 | private fun updateUI(value: ContactData?) { 28 | widget_contact_name.text = value?.name 29 | widget_contact_email.text = value?.email 30 | widget_contact_fingerprint.text = value?.keyId?.toFormattedHexText() 31 | widget_contact_created_at.text = prettyTime.format(value?.keyData?.firstOrNull()?.createAt) 32 | } 33 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/java/com/sujitech/tessercubecore/widget/ImageSwitch.kt: -------------------------------------------------------------------------------- 1 | package com.sujitech.tessercubecore.widget 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.widget.ImageButton 6 | import android.widget.ImageView 7 | import androidx.core.widget.ImageViewCompat 8 | 9 | class ImageSwitch : ImageButton { 10 | constructor(context: Context) : super(context) 11 | constructor(context: Context, attrs: AttributeSet) : super(context, attrs) 12 | constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) 13 | 14 | } -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/tessercubecore/src/main/res/drawable-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/tessercubecore/src/main/res/drawable-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/tessercubecore/src/main/res/drawable-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/tessercubecore/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/tessercubecore/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_account_circle_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_add_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_brightness_1_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_chat_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_contract_name_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_dashboard_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_done_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_edit_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_home_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_keyboard_toggle_icon.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_lock_outline_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_notifications_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_people_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_person_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_round_border.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 13 | 18 | -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_search_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_splash.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_tutorial_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/tessercubecore/src/main/res/drawable/ic_tutorial_1.png -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_tutorial_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/tessercubecore/src/main/res/drawable/ic_tutorial_2.png -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_tutorial_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionDev/TesserPG-Android/a573f7c66b465227b55af246f00b92794736cdd3/tessercubecore/src/main/res/drawable/ic_tutorial_3.png -------------------------------------------------------------------------------- /tessercubecore/src/main/res/drawable/ic_vpn_key_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /tessercubecore/src/main/res/layout/activity_import_contact.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 16 | 26 |