├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── .idea
└── vcs.xml
├── README.md
├── app
├── .gitignore
├── build.gradle
├── google-services.json
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── ru
│ │ └── ibakaidov
│ │ └── distypepro
│ │ └── ExampleInstrumentedTest.java
│ ├── debug
│ └── res
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ └── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── ru
│ │ │ └── ibakaidov
│ │ │ ├── .DS_Store
│ │ │ └── distypepro
│ │ │ ├── .DS_Store
│ │ │ ├── components
│ │ │ ├── BankGroup.java
│ │ │ ├── Component.java
│ │ │ └── InputGroup.java
│ │ │ ├── data
│ │ │ ├── CategoryManager.java
│ │ │ ├── Manager.java
│ │ │ └── StatementManager.java
│ │ │ ├── dialogs
│ │ │ ├── ConfirmDialog.java
│ │ │ ├── ContextDialog.java
│ │ │ └── InputDialog.java
│ │ │ ├── screens
│ │ │ ├── AuthActivity.java
│ │ │ ├── MainActivity.java
│ │ │ └── SpotlightActivity.java
│ │ │ ├── structures
│ │ │ ├── Category.java
│ │ │ └── Statement.java
│ │ │ └── utils
│ │ │ ├── Callback.java
│ │ │ ├── HashMapAdapter.java
│ │ │ ├── ProgressState.java
│ │ │ └── TTS.java
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ ├── ic_baseline_add_24.xml
│ │ ├── ic_baseline_arrow_back_24.xml
│ │ ├── ic_baseline_clear_24.xml
│ │ ├── ic_baseline_lock_24.xml
│ │ ├── ic_baseline_lock_open_24.xml
│ │ ├── ic_baseline_remove_red_eye_24.xml
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ ├── activity_auth.xml
│ │ ├── activity_main.xml
│ │ ├── activity_spotlight.xml
│ │ ├── bank_group.xml
│ │ ├── input_group.xml
│ │ └── input_prompt.xml
│ │ ├── menu
│ │ └── main_menu.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── values-ru-rRU
│ │ └── strings.xml
│ │ ├── values
│ │ ├── arrays.xml
│ │ ├── attrs.xml
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ ├── styles.xml
│ │ └── themes.xml
│ │ └── xml
│ │ ├── backup_rules.xml
│ │ └── data_extraction_rules.xml
│ └── test
│ └── java
│ └── ru
│ └── ibakaidov
│ └── distypepro
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a Java project with Gradle
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
3 |
4 | name: Andriod CI
5 |
6 | on:
7 | push:
8 | branches: [ master ]
9 | pull_request:
10 | branches: [ master ]
11 |
12 | jobs:
13 | build:
14 |
15 | runs-on: ubuntu-latest
16 |
17 | steps:
18 | - uses: actions/checkout@v3
19 | - name: set up JDK
20 | uses: actions/setup-java@v3
21 | with:
22 | java-version: '23'
23 | distribution: 'temurin'
24 | cache: gradle
25 |
26 | - name: Grant execute permission for gradlew
27 | run: chmod +x gradlew
28 | - name: Build with Gradle
29 | run: ./gradlew build
30 | - name: Archive Artifact
31 | uses: actions/upload-artifact@master
32 | with:
33 | name: apk
34 | path: app/build/outputs/apk/release/
35 | signin:
36 | runs-on: ubuntu-latest
37 | needs: build
38 | steps:
39 | - uses: actions/checkout@v4
40 | - name: Download Artifact
41 | uses: actions/download-artifact@master
42 | with:
43 | name: apk
44 | path: app/build/outputs/apk/release/
45 |
46 | - uses: r0adkll/sign-android-release@v1
47 | name: Sign app APK
48 | id: sign_app
49 | with:
50 | releaseDirectory: app/build/outputs/apk/release
51 | signingKeyBase64: ${{ secrets.SIGNING_KEY }}
52 | alias: main key
53 | keyStorePassword: ${{ secrets.KEYSTOREPASSWORD }}
54 | keyPassword: ${{ secrets.KEYPASSWORD }}
55 | env:
56 | BUILD_TOOLS_VERSION: "35.0.1"
57 |
58 | - uses: actions/upload-artifact@v4
59 | name: Upload signed build
60 | with:
61 | name: Signed app bundle
62 | path: ${{steps.sign_app.outputs.signedReleaseFile}}
--------------------------------------------------------------------------------
/.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/
39 |
40 | # Keystore files
41 | *.jks
42 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # LINKa. напиши
2 |
3 | Программа, переводящая напечатанный текст в речь и сохраняющая частые фразы. Подходит для людей, которые легко печатают на клавиатуре или экране планшета, но имеют проблемы с речью.
4 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'com.google.gms.google-services'
4 | }
5 |
6 | android {
7 | namespace 'ru.ibakaidov.distypepro'
8 | compileSdk 35
9 |
10 | defaultConfig {
11 | applicationId "ru.ibakaidov.distypepro"
12 | minSdk 21
13 | targetSdk 35
14 | versionCode 28
15 | versionName "3.2"
16 |
17 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
18 | }
19 |
20 | buildTypes {
21 | release {
22 | minifyEnabled false
23 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
24 | }
25 | }
26 | compileOptions {
27 | sourceCompatibility JavaVersion.VERSION_1_8
28 | targetCompatibility JavaVersion.VERSION_1_8
29 | }
30 | buildFeatures {
31 | viewBinding true
32 | }
33 | buildToolsVersion '35.0.1'
34 | }
35 |
36 | dependencies {
37 |
38 | implementation 'androidx.appcompat:appcompat:1.5.1'
39 | implementation 'com.google.android.material:material:1.7.0'
40 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
41 | implementation "com.github.permissions-dispatcher:permissionsdispatcher:4.8.0"
42 | implementation 'androidx.navigation:navigation-fragment:2.5.3'
43 | implementation 'androidx.navigation:navigation-ui:2.5.3'
44 | //noinspection GradleDynamicVersion
45 | implementation 'androidx.preference:preference:1.2.0'
46 |
47 | implementation 'com.afollestad.material-dialogs:input:3.3.0'
48 | implementation 'com.google.firebase:firebase-analytics:21.2.0'
49 |
50 | implementation 'com.github.bumptech.glide:glide:4.11.0'
51 | testImplementation 'junit:junit:4.13.2'
52 | androidTestImplementation 'androidx.test.ext:junit:1.1.4'
53 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
54 | implementation 'com.google.firebase:firebase-database:20.1.0'
55 | implementation 'com.google.firebase:firebase-auth:21.1.0'
56 | implementation 'com.firebaseui:firebase-ui-auth:8.0.2'
57 | }
58 |
--------------------------------------------------------------------------------
/app/google-services.json:
--------------------------------------------------------------------------------
1 | {
2 | "project_info": {
3 | "project_number": "800888317067",
4 | "firebase_url": "https://distypepro-android.firebaseio.com",
5 | "project_id": "distypepro-android",
6 | "storage_bucket": "distypepro-android.appspot.com"
7 | },
8 | "client": [
9 | {
10 | "client_info": {
11 | "mobilesdk_app_id": "1:800888317067:android:06e954d4007fb515",
12 | "android_client_info": {
13 | "package_name": "ru.ibakaidov.distypepro"
14 | }
15 | },
16 | "oauth_client": [
17 | {
18 | "client_id": "800888317067-g2fiacadak4adl89duvh7a5nabdhnlb6.apps.googleusercontent.com",
19 | "client_type": 1,
20 | "android_info": {
21 | "package_name": "ru.ibakaidov.distypepro",
22 | "certificate_hash": "46c6b789f46199df6b7706029ee7d0c72c1674ff"
23 | }
24 | },
25 | {
26 | "client_id": "800888317067-i91mbc3etv34tu07k5n8h4l58f0kohuj.apps.googleusercontent.com",
27 | "client_type": 1,
28 | "android_info": {
29 | "package_name": "ru.ibakaidov.distypepro",
30 | "certificate_hash": "bc06b3414b7fab8d58e8a710ee23e0c6e2a3963a"
31 | }
32 | },
33 | {
34 | "client_id": "800888317067-nbq3g1ghp4gsn2rmg5hanhckb6glafjn.apps.googleusercontent.com",
35 | "client_type": 3
36 | }
37 | ],
38 | "api_key": [
39 | {
40 | "current_key": "AIzaSyCNJUzqwMjvMKsFPxB9L1VbHHvO-4qi7IQ"
41 | }
42 | ],
43 | "services": {
44 | "appinvite_service": {
45 | "other_platform_oauth_client": [
46 | {
47 | "client_id": "800888317067-nbq3g1ghp4gsn2rmg5hanhckb6glafjn.apps.googleusercontent.com",
48 | "client_type": 3
49 | },
50 | {
51 | "client_id": "800888317067-gm7td75tp9i7o1bn94cskpibetbs9r59.apps.googleusercontent.com",
52 | "client_type": 2,
53 | "ios_info": {
54 | "bundle_id": "com.linka.linkaType"
55 | }
56 | }
57 | ]
58 | }
59 | }
60 | }
61 | ],
62 | "configuration_version": "1"
63 | }
--------------------------------------------------------------------------------
/app/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
--------------------------------------------------------------------------------
/app/src/androidTest/java/ru/ibakaidov/distypepro/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 | assertEquals("ru.ibakaidov.distypepro", appContext.getPackageName());
25 | }
26 | }
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linkasu/linkatype-android/c2ebe9f66bb88f1612820d3968dcfad3d22b4fb4/app/src/debug/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linkasu/linkatype-android/c2ebe9f66bb88f1612820d3968dcfad3d22b4fb4/app/src/debug/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linkasu/linkatype-android/c2ebe9f66bb88f1612820d3968dcfad3d22b4fb4/app/src/debug/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linkasu/linkatype-android/c2ebe9f66bb88f1612820d3968dcfad3d22b4fb4/app/src/debug/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linkasu/linkatype-android/c2ebe9f66bb88f1612820d3968dcfad3d22b4fb4/app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
15 |
16 |
21 |
24 |
27 |
28 |
29 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linkasu/linkatype-android/c2ebe9f66bb88f1612820d3968dcfad3d22b4fb4/app/src/main/java/ru/ibakaidov/.DS_Store
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/distypepro/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linkasu/linkatype-android/c2ebe9f66bb88f1612820d3968dcfad3d22b4fb4/app/src/main/java/ru/ibakaidov/distypepro/.DS_Store
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/distypepro/components/BankGroup.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro.components;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.util.Log;
6 | import android.view.View;
7 | import android.widget.AdapterView;
8 | import android.widget.ArrayAdapter;
9 | import android.widget.Button;
10 | import android.widget.GridView;
11 | import android.widget.ImageButton;
12 |
13 | import androidx.annotation.NonNull;
14 | import androidx.annotation.Nullable;
15 | import androidx.appcompat.widget.AppCompatButton;
16 | import androidx.recyclerview.widget.ListAdapter;
17 |
18 | import com.google.firebase.auth.FirebaseAuth;
19 | import com.google.firebase.database.DataSnapshot;
20 | import com.google.firebase.database.DatabaseError;
21 | import com.google.firebase.database.FirebaseDatabase;
22 | import com.google.firebase.database.ValueEventListener;
23 |
24 | import java.util.ArrayList;
25 | import java.util.HashMap;
26 | import java.util.LinkedHashMap;
27 | import java.util.MissingResourceException;
28 | import java.util.function.Consumer;
29 |
30 | import ru.ibakaidov.distypepro.R;
31 | import ru.ibakaidov.distypepro.data.CategoryManager;
32 | import ru.ibakaidov.distypepro.data.StatementManager;
33 | import ru.ibakaidov.distypepro.dialogs.ConfirmDialog;
34 | import ru.ibakaidov.distypepro.dialogs.ContextDialog;
35 | import ru.ibakaidov.distypepro.dialogs.InputDialog;
36 | import ru.ibakaidov.distypepro.structures.Category;
37 | import ru.ibakaidov.distypepro.utils.Callback;
38 | import ru.ibakaidov.distypepro.utils.HashMapAdapter;
39 | import ru.ibakaidov.distypepro.utils.TTS;
40 |
41 | public class BankGroup extends Component {
42 |
43 | private CategoryManager cm;
44 | private StatementManager sm;
45 | private GridView gridView;
46 | private ImageButton backButton;
47 | private ImageButton addButton;
48 |
49 | private TTS tts;
50 | private boolean state = false;
51 |
52 |
53 |
54 | public BankGroup(Context context, @Nullable AttributeSet attrs) {
55 | super(context, attrs);
56 | }
57 |
58 | @Override
59 | protected int getLayoutId() {
60 | return R.layout.bank_group;
61 | }
62 |
63 | @Override
64 | protected void initUI() {
65 | gridView = findViewById(R.id.gridview);
66 | addButton = findViewById(R.id.add_button);
67 | backButton = findViewById(R.id.back_button);
68 |
69 | backButton.setOnClickListener(new OnClickListener() {
70 | @Override
71 | public void onClick(View view) {
72 | setState(false);
73 | }
74 | });
75 |
76 | addButton.setOnClickListener(
77 | new OnClickListener() {
78 | @Override
79 | public void onClick(View view) {
80 | add();
81 | }
82 | }
83 | );
84 |
85 | gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
86 | @Override
87 | public void onItemClick(AdapterView> adapterView, View view, int i, long l) {
88 | HashMapAdapter adapter = (HashMapAdapter) adapterView.getAdapter();
89 | String key = adapter.getKey(i);
90 | String value = adapter.getItem(i);
91 | onItemSelected(key, value);
92 | }
93 |
94 | });
95 |
96 | gridView
97 | .setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
98 | @Override
99 | public boolean onItemLongClick(AdapterView> adapterView, View view, int i, long l) {
100 | HashMapAdapter adapter = (HashMapAdapter) adapterView.getAdapter();
101 | String key = adapter.getKey(i);
102 | String value = adapter.getItem(i);
103 | onLongItemClick(key, value);
104 |
105 | return false;
106 | }
107 | });
108 | cm = new CategoryManager();
109 |
110 | showCategories();
111 |
112 | }
113 |
114 | private void add() {
115 | InputDialog
116 | .showDialog(getContext(), R.string.create, new Callback() {
117 | @Override
118 | public void onDone(String res) {
119 | if(state){
120 | sm.create(res, new Callback() {
121 | @Override
122 | public void onDone(Object res) {
123 |
124 | }
125 | });
126 | } else {
127 | cm.create(res, new Callback() {
128 | @Override
129 | public void onDone(Object res) {
130 |
131 | }
132 | });
133 | }
134 | }
135 | });
136 | }
137 |
138 | private void onLongItemClick(String key, String value) {
139 | ContextDialog
140 | .show(getContext(), value, new Callback() {
141 | @Override
142 | public void onDone(ContextDialog.ContextDialogActions res) {
143 | if(res== ContextDialog.ContextDialogActions.edit){
144 | edit();
145 | } else {
146 | remove();
147 | }
148 | }
149 |
150 | private void remove() {
151 | ConfirmDialog
152 | .showConfirmDialog(getContext(), R.string.remove, new Callback() {
153 | @Override
154 | public void onDone(Object res) {
155 | if(getState()){
156 | sm.remove(key, new Callback() {
157 | @Override
158 | public void onDone(Object res) {
159 |
160 | }
161 | });
162 | } else {
163 | cm.remove(key, new Callback() {
164 | @Override
165 | public void onDone(Object res) {
166 |
167 | }
168 | });
169 | }
170 | }
171 | });
172 | }
173 |
174 | private void edit() {
175 | InputDialog
176 | .showDialog(getContext(), R.string.edit, value, new Callback() {
177 | @Override
178 | public void onDone(String res) {
179 | if(getState()){
180 | sm.edit(key, res, new Callback() {
181 | @Override
182 | public void onDone(Object res) {
183 |
184 | }
185 | });
186 | } else {
187 | cm.edit(key, res, new Callback() {
188 | @Override
189 | public void onDone(Object res) {
190 |
191 | }
192 | });
193 | }
194 | }
195 | });
196 | }
197 | });
198 | }
199 |
200 | private void onItemSelected(String key, String value) {
201 | if(getState()){
202 |
203 | tts.speak(value);
204 | } else {
205 | // categories
206 | sm = new StatementManager(key);
207 | setState(true);
208 |
209 | }
210 | }
211 |
212 |
213 | private boolean getState(){
214 | return state;
215 | }
216 |
217 | private void setState(boolean value){
218 | state = value;
219 | if(value){
220 | showStatements();
221 | backButton.setVisibility(VISIBLE);
222 | } else {
223 | showCategories();
224 | backButton.setVisibility(GONE);
225 | }
226 | }
227 |
228 | private void showCategories() {
229 |
230 | cm.getList(new Callback>() {
231 | @Override
232 | public void onDone(HashMap res) {
233 | if(getState()) return;
234 |
235 | HashMapAdapter adapter = new HashMapAdapter(getContext(), res);
236 | gridView.setAdapter(adapter);
237 | }
238 | });
239 |
240 | }
241 |
242 | private void showStatements() {
243 | if(!getState()) return;
244 | sm.getList(new Callback>() {
245 | @Override
246 | public void onDone(HashMap res) {
247 | HashMapAdapter adapter = new HashMapAdapter(getContext(), res);
248 | gridView.setAdapter(adapter);
249 | }
250 | });
251 | }
252 |
253 | public void setTts(TTS tts) {
254 | this.tts = tts;
255 | }
256 |
257 | public void back() {
258 | setState(false);
259 | }
260 | }
261 |
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/distypepro/components/Component.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro.components;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.LinearLayout;
9 |
10 | import androidx.annotation.Nullable;
11 |
12 | import ru.ibakaidov.distypepro.R;
13 |
14 | public abstract class Component extends LinearLayout {
15 |
16 | protected int layoutId;
17 |
18 | public Component(Context context, @Nullable AttributeSet attrs) {
19 | super(context, attrs);
20 | inflate(context);
21 | }
22 |
23 | private void inflate(Context context) {
24 | LayoutInflater layoutInflater = (LayoutInflater) context
25 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
26 | layoutInflater.inflate(getLayoutId(), this, true);
27 | initUI();
28 | }
29 |
30 | protected abstract int getLayoutId();
31 |
32 | protected abstract void initUI();
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/distypepro/components/InputGroup.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro.components;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.AdapterView;
8 | import android.widget.ArrayAdapter;
9 | import android.widget.Button;
10 | import android.widget.EditText;
11 | import android.widget.ImageButton;
12 | import android.widget.Spinner;
13 |
14 | import androidx.annotation.Nullable;
15 |
16 | import com.google.firebase.analytics.FirebaseAnalytics;
17 |
18 | import ru.ibakaidov.distypepro.R;
19 | import ru.ibakaidov.distypepro.screens.SpotlightActivity;
20 | import ru.ibakaidov.distypepro.utils.Callback;
21 | import ru.ibakaidov.distypepro.utils.ProgressState;
22 | import ru.ibakaidov.distypepro.utils.TTS;
23 |
24 | public class InputGroup extends Component {
25 | private TTS tts;
26 | private EditText ttsEditText;
27 | private Button sayButton;
28 | private ImageButton spotlightButton;
29 | private Spinner chatSpinner;
30 | private int prevSpinnerValue = 0;
31 | private String[] textCache = new String[] {"", "", ""};
32 |
33 | public InputGroup(Context context, @Nullable AttributeSet attrs) {
34 | super(context, attrs);
35 | }
36 |
37 | public void setTts(TTS tts) {
38 | this.tts = tts;
39 |
40 | tts.setOnPlayCallback(new Callback() {
41 | @Override
42 | public void onDone(ProgressState res) {
43 | sayButton.setText(res == ProgressState.START?R.string.stop:R.string.say);
44 | }
45 | });
46 | }
47 |
48 | @Override
49 | protected void initUI() {
50 | ttsEditText = findViewById(R.id.text_to_speech_edittext);
51 | sayButton = findViewById(R.id.say_button);
52 | spotlightButton = findViewById(R.id.spotlight_button);
53 |
54 |
55 | setOnClickListener(new OnClickListener() {
56 | @Override
57 | public void onClick(View view) {
58 | if(ttsEditText.hasFocus()){
59 | ttsEditText.clearFocus();
60 | }
61 | }
62 | });
63 | View v = this;
64 | ttsEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
65 | @Override
66 | public void onFocusChange(View view, boolean b) {
67 | ViewGroup.LayoutParams params = v.getLayoutParams();
68 | params.height = b?LayoutParams.MATCH_PARENT: ViewGroup.LayoutParams.WRAP_CONTENT;
69 | v.setLayoutParams(params);
70 | }
71 | });
72 |
73 | sayButton.setOnClickListener(new OnClickListener() {
74 | @Override
75 | public void onClick(View view) {
76 | say();
77 | }
78 | });
79 |
80 | spotlightButton.setOnClickListener(new OnClickListener() {
81 | @Override
82 | public void onClick(View view) {
83 | spotlight();
84 | }
85 | });
86 |
87 | }
88 |
89 | private void setText(String s) {
90 | ttsEditText.setText(s);
91 | }
92 |
93 | private void spotlight() {
94 | SpotlightActivity
95 | .show(getContext(), getText());
96 |
97 | FirebaseAnalytics
98 | .getInstance(getContext())
99 | .logEvent("spotlight", null);
100 | }
101 |
102 | @Override
103 | protected int getLayoutId() {
104 | return R.layout.input_group;
105 | }
106 |
107 | private void say() {
108 | String text = getText();
109 | tts.speak(text);
110 | FirebaseAnalytics
111 | .getInstance(getContext())
112 | .logEvent("say", null);
113 | }
114 |
115 | private String getText() {
116 | return ttsEditText.getText().toString();
117 | }
118 |
119 | public void setChatSpinner(Spinner chatSpinner) {
120 | this.chatSpinner = chatSpinner;
121 | ArrayAdapter adapter = new ArrayAdapter(getContext(), androidx.appcompat.R.layout.support_simple_spinner_dropdown_item, new String[]{"1", "2", "3"});
122 | chatSpinner.setAdapter(adapter);
123 |
124 | chatSpinner
125 | .setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
126 | @Override
127 | public void onItemSelected(AdapterView> adapterView, View view, int i, long l) {
128 | textCache[prevSpinnerValue] = getText();
129 | setText(textCache[i]);
130 | prevSpinnerValue = i;
131 |
132 | }
133 |
134 | @Override
135 | public void onNothingSelected(AdapterView> adapterView) {
136 |
137 | }
138 | });
139 | }
140 |
141 | public void clear() {
142 | ttsEditText.setText("");
143 | }
144 |
145 | public void back() {
146 | ttsEditText.clearFocus();
147 | }
148 | }
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/distypepro/data/CategoryManager.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro.data;
2 |
3 | import android.os.Build;
4 |
5 | import androidx.annotation.NonNull;
6 | import androidx.annotation.Nullable;
7 | import androidx.annotation.RequiresApi;
8 |
9 | import com.google.firebase.auth.FirebaseAuth;
10 | import com.google.firebase.database.DataSnapshot;
11 | import com.google.firebase.database.DatabaseError;
12 | import com.google.firebase.database.DatabaseReference;
13 | import com.google.firebase.database.FirebaseDatabase;
14 | import com.google.firebase.database.ValueEventListener;
15 |
16 | import java.util.ArrayList;
17 | import java.util.Comparator;
18 | import java.util.Date;
19 | import java.util.HashMap;
20 | import java.util.Map;
21 | import java.util.function.Consumer;
22 |
23 | import ru.ibakaidov.distypepro.structures.Category;
24 | import ru.ibakaidov.distypepro.utils.Callback;
25 |
26 | public class CategoryManager extends Manager {
27 |
28 | @Override
29 | public void getList(Callback> callback) {
30 | getRoot()
31 | .orderByChild("created")
32 | .addValueEventListener(new ValueEventListener() {
33 | @RequiresApi(api = Build.VERSION_CODES.N)
34 | @Override
35 | public void onDataChange(@NonNull DataSnapshot snapshot) {
36 | Iterable children = snapshot.getChildren();
37 | HashMap res = new HashMap<>();
38 | ArrayList list = new ArrayList();
39 | while( children.iterator().hasNext()){
40 | DataSnapshot s = children.iterator().next();
41 | Category category = Category.fromHashMap((HashMap) s.getValue());
42 | list.add(category);
43 | }
44 | list.sort(new Comparator() {
45 | @Override
46 | public int compare(Category t1, Category t2) {
47 | return (int) (t2.created-t1.created);
48 | }
49 | });
50 | list.forEach(new Consumer() {
51 | @Override
52 | public void accept(Category category) {
53 | res.put(category.id, category.label);
54 | }
55 | });
56 | callback.onDone(res);
57 | }
58 |
59 | @Override
60 | public void onCancelled(@NonNull DatabaseError error) {
61 | callback.onError(error.toException());
62 | }
63 | });
64 | }
65 |
66 | @Override
67 | public DatabaseReference getRoot() {
68 | return FirebaseDatabase
69 | .getInstance()
70 | .getReference("users/"+ FirebaseAuth.getInstance().getCurrentUser().getUid())
71 | .child("Category");
72 | }
73 |
74 | @Override
75 | public void edit(String key, String value, Callback callback) {
76 | Map update = new HashMap<>();
77 | update.put("label", value);
78 | getRoot()
79 | .child(key)
80 | .updateChildren(update);
81 | }
82 |
83 | @Override
84 | public void create(String res, Callback callback) {
85 | DatabaseReference r = getRoot()
86 | .push();
87 | Map update = new HashMap<>();
88 | update.put("label", res);
89 | update.put("id", r.getKey());
90 | update.put("created", new Date().getTime());
91 | r.updateChildren(update, new DatabaseReference.CompletionListener() {
92 | @Override
93 | public void onComplete(@Nullable DatabaseError error, @NonNull DatabaseReference ref) {
94 | callback.onDone(null);
95 | }
96 | });
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/distypepro/data/Manager.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro.data;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 |
6 | import com.google.firebase.database.DatabaseError;
7 | import com.google.firebase.database.DatabaseReference;
8 |
9 | import java.util.HashMap;
10 |
11 | import ru.ibakaidov.distypepro.utils.Callback;
12 |
13 | public abstract class Manager {
14 |
15 | public abstract void getList(Callback> callback);
16 | public abstract DatabaseReference getRoot();
17 |
18 | public void remove(String key, Callback callback) {
19 | getRoot().child(key).removeValue(new DatabaseReference.CompletionListener() {
20 | @Override
21 | public void onComplete(@Nullable DatabaseError error, @NonNull DatabaseReference ref) {
22 | if(error!=null){
23 | callback.onError(error.toException());
24 | return;
25 | }
26 | callback.onDone(null);
27 | }
28 | });
29 | }
30 |
31 | public abstract void edit(String key, String value, Callback callback);
32 |
33 | public abstract void create(String res, Callback callback);
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/distypepro/data/StatementManager.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro.data;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 |
6 | import com.google.firebase.auth.FirebaseAuth;
7 | import com.google.firebase.database.DataSnapshot;
8 | import com.google.firebase.database.DatabaseError;
9 | import com.google.firebase.database.DatabaseReference;
10 | import com.google.firebase.database.FirebaseDatabase;
11 | import com.google.firebase.database.ValueEventListener;
12 |
13 | import java.util.Date;
14 | import java.util.HashMap;
15 | import java.util.Map;
16 |
17 | import ru.ibakaidov.distypepro.structures.Category;
18 | import ru.ibakaidov.distypepro.structures.Statement;
19 | import ru.ibakaidov.distypepro.utils.Callback;
20 |
21 | public class StatementManager extends Manager {
22 |
23 |
24 | private String categoryId;
25 |
26 | public StatementManager(String categoryId){
27 | this.categoryId = categoryId;
28 | }
29 |
30 | @Override
31 | public void getList(Callback> callback) {
32 | getRoot()
33 | .orderByChild("created")
34 | .addValueEventListener(new ValueEventListener() {
35 | @Override
36 | public void onDataChange(@NonNull DataSnapshot snapshot) {
37 | Iterable children = snapshot.getChildren();
38 | HashMap res = new HashMap<>();
39 | while( children.iterator().hasNext()){
40 | DataSnapshot s = children.iterator().next();
41 | Statement statement = Statement.fromHashMap((HashMap) s.getValue());
42 | res.put(statement.id, statement.text);
43 | }
44 | callback.onDone(res);
45 | }
46 |
47 | @Override
48 | public void onCancelled(@NonNull DatabaseError error) {
49 |
50 | }
51 | });
52 | }
53 |
54 | @Override
55 | public DatabaseReference getRoot() {
56 | return FirebaseDatabase
57 | .getInstance()
58 | .getReference("users/"+ FirebaseAuth.getInstance().getCurrentUser().getUid()+"/Category/"+categoryId+"/statements/");
59 | }
60 |
61 | @Override
62 | public void edit(String key, String value, Callback callback) {
63 | Map update = new HashMap<>();
64 | update.put("text", value);
65 | getRoot()
66 | .child(key)
67 | .updateChildren(update);
68 | }
69 |
70 | @Override
71 | public void create(String res, Callback callback) {
72 | DatabaseReference r = getRoot()
73 | .push();
74 | Map update = new HashMap<>();
75 | update.put("text", res);
76 | update.put("id", r.getKey());
77 | update.put("categoryId", categoryId);
78 | update.put("created", new Date().getTime());
79 |
80 | r.updateChildren(update, new DatabaseReference.CompletionListener() {
81 | @Override
82 | public void onComplete(@Nullable DatabaseError error, @NonNull DatabaseReference ref) {
83 | callback.onDone(null);
84 | }
85 | });
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/distypepro/dialogs/ConfirmDialog.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro.dialogs;
2 |
3 |
4 | import android.app.AlertDialog;
5 | import android.content.Context;
6 | import android.content.DialogInterface;
7 |
8 | import androidx.annotation.StringRes;
9 |
10 | import ru.ibakaidov.distypepro.R;
11 | import ru.ibakaidov.distypepro.utils.Callback;
12 |
13 | public class ConfirmDialog {
14 | public static void showConfirmDialog(Context context, @StringRes int title, Callback callback){
15 | AlertDialog.Builder builder = new AlertDialog.Builder(context);
16 | builder
17 | .setTitle(title)
18 | .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
19 | @Override
20 | public void onClick(DialogInterface dialog, int which) {
21 | callback.onError(null);
22 | }
23 | })
24 | .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
25 | @Override
26 | public void onClick(DialogInterface dialog, int which) {
27 | callback.onDone(null);
28 | }
29 | })
30 | .show();
31 | }
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/distypepro/dialogs/ContextDialog.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro.dialogs;
2 |
3 | import android.app.AlertDialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 |
7 | import ru.ibakaidov.distypepro.R;
8 | import ru.ibakaidov.distypepro.utils.Callback;
9 |
10 | public class ContextDialog {
11 |
12 | public static void show(Context context, String title, Callback callback){
13 | // setup the alert builder
14 | AlertDialog.Builder builder = new AlertDialog.Builder(context);
15 | builder.setTitle(title);
16 |
17 | builder.setItems(R.array.set_context_actions, new DialogInterface.OnClickListener() {
18 | @Override
19 | public void onClick(DialogInterface dialog, int which) {
20 | callback.onDone(which==0?ContextDialogActions.edit:ContextDialogActions.remove);
21 | }
22 | })
23 | .setNegativeButton(R.string.cancel, null);
24 |
25 | // create and show the alert dialog
26 | AlertDialog dialog = builder.create();
27 | dialog.show();
28 | }
29 |
30 | public static enum ContextDialogActions{
31 | edit,
32 | remove
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/distypepro/dialogs/InputDialog.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro.dialogs;
2 |
3 |
4 | import android.app.AlertDialog;
5 | import android.content.Context;
6 | import android.content.DialogInterface;
7 | import android.text.InputType;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.widget.EditText;
11 |
12 | import androidx.annotation.Nullable;
13 | import androidx.annotation.StringRes;
14 |
15 | import ru.ibakaidov.distypepro.R;
16 | import ru.ibakaidov.distypepro.utils.Callback;
17 |
18 | public class InputDialog {
19 | public static void showDialog(Context context, @StringRes int title, int type, Callback listener) {
20 | showDialog(context, title, type, null, listener);
21 | }
22 | public static void showDialog(Context context, @StringRes int title, Callback listener) {
23 | showDialog(context, title, null, listener);
24 | }
25 |
26 | public static void showDialog(Context context, @StringRes int title, @Nullable String currentValue, Callback listener) {
27 | showDialog(context, title, InputType.TYPE_CLASS_TEXT, currentValue, listener);
28 | }
29 |
30 | public static void showDialog(Context context, @StringRes int title, int type, @Nullable String currentValue, Callback listener) {
31 | LayoutInflater li = LayoutInflater.from(context);
32 | View promptsView = li.inflate(R.layout.input_prompt, null);
33 | final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
34 | alertDialogBuilder.setView(promptsView);
35 |
36 | final EditText userInput = (EditText) promptsView
37 | .findViewById(R.id.input_prompt);
38 | if (currentValue != null) {
39 | userInput.setText(currentValue);
40 | }
41 | userInput.setInputType(type);
42 | alertDialogBuilder
43 | .setTitle(title)
44 | .setPositiveButton(R.string.ok,
45 | new DialogInterface.OnClickListener() {
46 | public void onClick(DialogInterface dialog, int id) {
47 | /** DO THE METHOD HERE WHEN PROCEED IS CLICKED*/
48 | String user_text = (userInput.getText()).toString().trim();
49 | if (!user_text.equals("")) {
50 | listener.onDone(user_text);
51 | } else {
52 | listener.onError(null);
53 | }
54 | dialog.dismiss();
55 | }
56 |
57 | })
58 | .setNegativeButton(R.string.cancel,
59 | new DialogInterface.OnClickListener() {
60 | public void onClick(DialogInterface dialog, int id) {
61 | dialog.dismiss();
62 | listener.onError(null);
63 | }
64 |
65 | }
66 |
67 | ).setOnCancelListener(new DialogInterface.OnCancelListener() {
68 | @Override
69 | public void onCancel(DialogInterface dialog) {
70 | listener.onError(null);
71 | }
72 | });
73 |
74 | // create alert dialog
75 | AlertDialog alertDialog = alertDialogBuilder.create();
76 | alertDialog.setOnShowListener(new DialogInterface.OnShowListener() {
77 | @Override
78 | public void onShow(DialogInterface dialog) {
79 | userInput.requestFocus();
80 | }
81 | });
82 | // show it
83 | alertDialog.show();
84 |
85 | }
86 | }
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/distypepro/screens/AuthActivity.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro.screens;
2 |
3 | import androidx.activity.result.ActivityResultCallback;
4 | import androidx.activity.result.ActivityResultLauncher;
5 | import androidx.appcompat.app.AppCompatActivity;
6 |
7 | import android.content.Intent;
8 | import android.os.Bundle;
9 |
10 | import com.firebase.ui.auth.AuthUI;
11 | import com.firebase.ui.auth.FirebaseAuthUIActivityResultContract;
12 | import com.firebase.ui.auth.data.model.FirebaseAuthUIAuthenticationResult;
13 | import com.google.firebase.auth.FirebaseAuth;
14 | import com.google.firebase.auth.FirebaseUser;
15 |
16 | import java.util.Arrays;
17 | import java.util.List;
18 |
19 | import ru.ibakaidov.distypepro.R;
20 |
21 | public class AuthActivity extends AppCompatActivity {
22 | private final ActivityResultLauncher signInLauncher = registerForActivityResult(
23 | new FirebaseAuthUIActivityResultContract(),
24 | new ActivityResultCallback() {
25 | @Override
26 | public void onActivityResult(FirebaseAuthUIAuthenticationResult result) {
27 | onSignInResult(result);
28 | }
29 | }
30 | );
31 |
32 | @Override
33 | protected void onCreate(Bundle savedInstanceState) {
34 | super.onCreate(savedInstanceState);
35 | setContentView(R.layout.activity_auth);
36 |
37 |
38 | if(getCurrentUser()==null) {
39 | auth();
40 | } else {
41 | initUI();
42 | }
43 |
44 | }
45 |
46 | private void initUI() {
47 | Intent intent = new Intent(this, MainActivity.class);
48 | startActivity(intent);
49 | finish();
50 | }
51 |
52 | private FirebaseUser getCurrentUser() {
53 | return FirebaseAuth.getInstance().getCurrentUser();
54 | }
55 |
56 | private void auth() {
57 | List providers = Arrays.asList(
58 | new AuthUI.IdpConfig.EmailBuilder().build());
59 |
60 | Intent signInIntent = AuthUI.getInstance()
61 | .createSignInIntentBuilder()
62 | .setAvailableProviders(providers)
63 | .setIsSmartLockEnabled(false)
64 | .build();
65 | signInLauncher.launch(signInIntent);
66 | }
67 |
68 | private void onSignInResult(FirebaseAuthUIAuthenticationResult result) {
69 | if(result.getResultCode() == RESULT_OK){
70 | initUI();
71 | }
72 |
73 | }
74 |
75 | }
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/distypepro/screens/MainActivity.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro.screens;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.appcompat.app.AppCompatActivity;
5 |
6 | import android.content.Intent;
7 | import android.os.Bundle;
8 | import android.provider.Settings;
9 | import android.view.ContextMenu;
10 | import android.view.Menu;
11 | import android.view.MenuInflater;
12 | import android.view.MenuItem;
13 | import android.view.View;
14 | import android.widget.Spinner;
15 |
16 | import com.google.firebase.analytics.FirebaseAnalytics;
17 | import com.google.firebase.database.FirebaseDatabase;
18 |
19 | import ru.ibakaidov.distypepro.R;
20 | import ru.ibakaidov.distypepro.components.BankGroup;
21 | import ru.ibakaidov.distypepro.components.InputGroup;
22 | import ru.ibakaidov.distypepro.utils.TTS;
23 |
24 | public class MainActivity extends AppCompatActivity {
25 |
26 |
27 | private InputGroup inputGroup;
28 | private BankGroup bankGroup;
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | FirebaseDatabase
33 | .getInstance()
34 | .setPersistenceEnabled(true);
35 | FirebaseAnalytics
36 | .getInstance(this);
37 | setContentView(R.layout.activity_main);
38 | TTS tts = new TTS(this);
39 | inputGroup = findViewById(R.id.input_group);
40 | inputGroup.setTts(tts);
41 | bankGroup = findViewById(R.id.bank_group);
42 | bankGroup.setTts(tts);
43 |
44 |
45 | }
46 | @Override
47 | public boolean onCreateOptionsMenu(Menu menu) {
48 | MenuInflater inflater = getMenuInflater();
49 | inflater.inflate(R.menu.main_menu, menu);
50 | Spinner spinner = (Spinner) menu.findItem(R.id.chats_spinner).getActionView();
51 | inputGroup.setChatSpinner(spinner);
52 | return true;
53 | }
54 |
55 | @Override
56 | public boolean onOptionsItemSelected(@NonNull MenuItem item) {
57 | switch (item.getItemId()){
58 | case R.id.clear_menu_item:
59 | inputGroup.clear();
60 | break;
61 | case R.id.settings_menu_item:
62 | Intent intent = new Intent();
63 | intent.setAction("com.android.settings.TTS_SETTINGS");
64 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
65 | startActivity(intent);
66 |
67 | break;
68 | }
69 | return super.onOptionsItemSelected(item);
70 | }
71 |
72 | @Override
73 | public void onBackPressed() {
74 | inputGroup.back();
75 | bankGroup.back();
76 | }
77 | }
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/distypepro/screens/SpotlightActivity.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro.screens;
2 |
3 | import android.annotation.SuppressLint;
4 |
5 | import androidx.appcompat.app.ActionBar;
6 | import androidx.appcompat.app.AppCompatActivity;
7 |
8 | import android.content.Context;
9 | import android.content.Intent;
10 | import android.os.Build;
11 | import android.os.Bundle;
12 | import android.os.Handler;
13 | import android.os.Looper;
14 | import android.view.MotionEvent;
15 | import android.view.View;
16 | import android.view.WindowInsets;
17 | import android.widget.TextView;
18 |
19 | import ru.ibakaidov.distypepro.databinding.ActivitySpotlightBinding;
20 | import ru.ibakaidov.distypepro.R;
21 | /**
22 | * An example full-screen activity that shows and hides the system UI (i.e.
23 | * status bar and navigation/system bar) with user interaction.
24 | */
25 | public class SpotlightActivity extends AppCompatActivity {
26 | /**
27 | * Whether or not the system UI should be auto-hidden after
28 | * {@link #AUTO_HIDE_DELAY_MILLIS} milliseconds.
29 | */
30 | private static final boolean AUTO_HIDE = true;
31 |
32 | /**
33 | * If {@link #AUTO_HIDE} is set, the number of milliseconds to wait after
34 | * user interaction before hiding the system UI.
35 | */
36 | private static final int AUTO_HIDE_DELAY_MILLIS = 3000;
37 |
38 | /**
39 | * Some older devices needs a small delay between UI widget updates
40 | * and a change of the status and navigation bar.
41 | */
42 | private static final int UI_ANIMATION_DELAY = 300;
43 | private final Handler mHideHandler = new Handler(Looper.myLooper());
44 | private View mContentView;
45 | private final Runnable mHidePart2Runnable = new Runnable() {
46 | @SuppressLint("InlinedApi")
47 | @Override
48 | public void run() {
49 | // Delayed removal of status and navigation bar
50 | if (Build.VERSION.SDK_INT >= 30) {
51 | mContentView.getWindowInsetsController().hide(
52 | WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
53 | } else {
54 | // Note that some of these constants are new as of API 16 (Jelly Bean)
55 | // and API 19 (KitKat). It is safe to use them, as they are inlined
56 | // at compile-time and do nothing on earlier devices.
57 | mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
58 | | View.SYSTEM_UI_FLAG_FULLSCREEN
59 | | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
60 | | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
61 | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
62 | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
63 | }
64 | }
65 | };
66 | private View mControlsView;
67 | private final Runnable mShowPart2Runnable = new Runnable() {
68 | @Override
69 | public void run() {
70 | // Delayed display of UI elements
71 | ActionBar actionBar = getSupportActionBar();
72 | if (actionBar != null) {
73 | actionBar.show();
74 | }
75 | mControlsView.setVisibility(View.VISIBLE);
76 | }
77 | };
78 | private boolean mVisible;
79 | private ActivitySpotlightBinding binding;
80 |
81 | @Override
82 | protected void onCreate(Bundle savedInstanceState) {
83 | super.onCreate(savedInstanceState);
84 |
85 | binding = ActivitySpotlightBinding.inflate(getLayoutInflater());
86 | setContentView(binding.getRoot());
87 |
88 |
89 |
90 | TextView textView = (TextView) findViewById(R.id.fullscreen_content);
91 |
92 | Bundle bundle = getIntent().getExtras();
93 |
94 | String text = bundle.getString("text");
95 | textView.setText(text);
96 |
97 |
98 | }
99 |
100 | public static void show(Context cxt, String text) {
101 | Intent intent = new Intent(cxt, SpotlightActivity.class);
102 | Bundle bundle = new Bundle();
103 | bundle.putString("text", text);
104 | intent.putExtras(bundle);
105 | cxt.startActivity(intent);
106 | }
107 | }
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/distypepro/structures/Category.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro.structures;
2 |
3 | import java.util.HashMap;
4 |
5 | public class Category {
6 |
7 | public long created = 0;
8 | public String id = null;
9 | public String label = null;
10 |
11 | public Category( String id, String label, long created) {
12 |
13 | this.created = created;
14 | this.id = id;
15 | this.label = label;
16 | }
17 |
18 | @Override
19 | public String toString() {
20 | return label;
21 | }
22 |
23 | public static Category fromHashMap(HashMap hashMap){
24 | long created = hashMap.containsKey("created")? (long) hashMap.get("created"):0;
25 | String id = (String) hashMap.get("id");
26 | String label = (String) hashMap.get("label");
27 |
28 | return new Category(id, label, created);
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/distypepro/structures/Statement.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro.structures;
2 |
3 | import java.util.HashMap;
4 |
5 | public class Statement {
6 | public String categoryId;
7 | public long created;
8 | public String id;
9 | public String text;
10 |
11 | public Statement(String id, String categoryId, String text, long created){
12 |
13 | this.id = id;
14 | this.categoryId = categoryId;
15 | this.text = text;
16 | this.created = created;
17 | }
18 |
19 |
20 | public static Statement fromHashMap(HashMap hashMap){
21 | long created = hashMap.containsKey("created")? (long) hashMap.get("created"):0;
22 | String id = (String) hashMap.get("id");
23 | String categoryId = (String) hashMap.get("categoryId");
24 | String text = (String) hashMap.get("text");
25 |
26 | return new Statement(id,categoryId, text, created);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/distypepro/utils/Callback.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro.utils;
2 |
3 | public abstract class Callback {
4 | public abstract void onDone(T res);
5 | public void onError(Exception e){}
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/distypepro/utils/HashMapAdapter.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro.utils;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.BaseAdapter;
8 | import android.widget.TextView;
9 |
10 | import java.util.HashMap;
11 |
12 | public class HashMapAdapter extends BaseAdapter {
13 | private Context context;
14 | private HashMap mData;
15 | private String[] mKeys;
16 | public HashMapAdapter(Context context, HashMap data){
17 | this.context = context;
18 | mData = data;
19 | mKeys = mData.keySet().toArray(new String[data.size()]);
20 | }
21 |
22 | @Override
23 | public int getCount() {
24 | return mData.size();
25 | }
26 |
27 | public String[] getEntry(int position){
28 | return new String[] {mKeys[position], getItem(position)};
29 | }
30 |
31 | @Override
32 | public String getItem(int position) {
33 | return mData.get(mKeys[position]);
34 | }
35 |
36 | @Override
37 | public long getItemId(int arg0) {
38 | return arg0;
39 | }
40 |
41 | @Override
42 | public View getView(int pos, View convertView, ViewGroup parent) {
43 | if (convertView == null) {
44 | convertView = LayoutInflater.from(context).
45 | inflate(androidx.appcompat.R.layout.support_simple_spinner_dropdown_item, parent, false);
46 | }
47 | String value = getItem(pos);
48 | ((TextView) convertView).setText(value);
49 | return convertView;
50 | }
51 |
52 | public String getKey(int position) {
53 | return mKeys[position];
54 | }
55 | }
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/distypepro/utils/ProgressState.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro.utils;
2 |
3 | public enum ProgressState {
4 | START,
5 | STOP
6 | }
7 |
--------------------------------------------------------------------------------
/app/src/main/java/ru/ibakaidov/distypepro/utils/TTS.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro.utils;
2 |
3 | import android.content.Context;
4 | import android.speech.tts.TextToSpeech;
5 | import android.speech.tts.UtteranceProgressListener;
6 | import android.speech.tts.Voice;
7 |
8 | import java.io.File;
9 | import java.util.Set;
10 | import java.util.UUID;
11 |
12 | public class TTS {
13 |
14 | private final Context context;
15 | private final TextToSpeech tts;
16 | private Callback onInitCallback;
17 | private Callback onPlayCallback;
18 |
19 | public TTS(Context context){
20 | this.context = context;
21 | tts = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
22 | @Override
23 | public void onInit(int status) {
24 | if(onInitCallback!=null){
25 | onInitCallback.onDone(status);
26 | }
27 | }
28 | });
29 | }
30 |
31 | public void setOnPlayCallback(Callback onPlayCallback) {
32 |
33 | this.onPlayCallback = onPlayCallback;
34 |
35 | tts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
36 | @Override
37 | public void onStart(String s) {
38 | onPlayCallback.onDone(ProgressState.START);
39 | }
40 |
41 | @Override
42 | public void onDone(String s) {
43 | onPlayCallback.onDone(ProgressState.STOP);
44 | }
45 |
46 | @Override
47 | public void onError(String s) {
48 |
49 | }
50 | });
51 | }
52 |
53 | public void setOnInitCallback(Callback onInitCallback) {
54 | this.onInitCallback = onInitCallback;
55 | }
56 |
57 | public Set getVoices(){
58 | return tts.getVoices();
59 | }
60 | public void speak(String text){
61 | if(tts.isSpeaking()){
62 | tts.stop();
63 | onPlayCallback.onDone(ProgressState.STOP);
64 | return;
65 | }
66 |
67 | tts.speak(text, TextToSpeech.QUEUE_FLUSH, null, "1");
68 | }
69 |
70 | public File speakToBuffer(String text) throws Exception {
71 | File file = new File(context.getCacheDir(), UUID.randomUUID().toString()+".wav");
72 |
73 | int res = tts.synthesizeToFile(text, null, file,null);
74 | if(res!= TextToSpeech.SUCCESS) throw new Exception("synth error");
75 | return file;
76 |
77 | }
78 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_add_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_arrow_back_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_clear_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_lock_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_lock_open_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_remove_red_eye_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_auth.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
14 |
15 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_spotlight.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
13 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/bank_group.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
14 |
18 |
26 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/input_group.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
13 |
17 |
23 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/input_prompt.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/main_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linkasu/linkatype-android/c2ebe9f66bb88f1612820d3968dcfad3d22b4fb4/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linkasu/linkatype-android/c2ebe9f66bb88f1612820d3968dcfad3d22b4fb4/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linkasu/linkatype-android/c2ebe9f66bb88f1612820d3968dcfad3d22b4fb4/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linkasu/linkatype-android/c2ebe9f66bb88f1612820d3968dcfad3d22b4fb4/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linkasu/linkatype-android/c2ebe9f66bb88f1612820d3968dcfad3d22b4fb4/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linkasu/linkatype-android/c2ebe9f66bb88f1612820d3968dcfad3d22b4fb4/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linkasu/linkatype-android/c2ebe9f66bb88f1612820d3968dcfad3d22b4fb4/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linkasu/linkatype-android/c2ebe9f66bb88f1612820d3968dcfad3d22b4fb4/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linkasu/linkatype-android/c2ebe9f66bb88f1612820d3968dcfad3d22b4fb4/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linkasu/linkatype-android/c2ebe9f66bb88f1612820d3968dcfad3d22b4fb4/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/values-ru-rRU/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | LINKa напиши
4 |
5 | Сказать
6 | Настройки
7 | Очистить
8 | Голос
9 | Остановить
10 | ОК
11 | Отмена
12 | Изменить
13 | Удалить
14 | Создать
15 |
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - Reply
5 | - Reply to all
6 |
7 |
8 |
9 | - reply
10 | - reply_all
11 |
12 |
13 | - @string/edit
14 | - @string/remove
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #197377
4 | #bed64f
5 | #fbcc30
6 | #000
7 | #FFF
8 | #FF039BE5
9 | #FF01579B
10 | #FF40C4FF
11 | #FF00B0FF
12 | #66000000
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | LINKa type
3 | Say
4 | Settings
5 | Clear
6 | Voice
7 | Stop
8 | OK
9 | Cancel
10 | Edit
11 | Remove
12 | Create
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
27 |
28 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/backup_rules.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/data_extraction_rules.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 |
19 |
--------------------------------------------------------------------------------
/app/src/test/java/ru/ibakaidov/distypepro/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package ru.ibakaidov.distypepro;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | dependencies {
3 | classpath 'com.google.gms:google-services:4.3.14'
4 | }
5 | }// Top-level build file where you can add configuration options common to all sub-projects/modules.
6 | plugins {
7 | id 'com.android.application' version '8.8.2' apply false
8 | id 'com.android.library' version '8.8.2' apply false
9 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Enables namespacing of each library's R class so that its R class includes only the
19 | # resources declared in the library itself and none from the library's dependencies,
20 | # thereby reducing the size of the R class for that library
21 | android.nonTransitiveRClass=true
22 | android.defaults.buildfeatures.buildconfig=true
23 | android.nonFinalResIds=false
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linkasu/linkatype-android/c2ebe9f66bb88f1612820d3968dcfad3d22b4fb4/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-8.10.2-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 | # SPDX-License-Identifier: Apache-2.0
19 | #
20 |
21 | ##############################################################################
22 | #
23 | # Gradle start up script for POSIX generated by Gradle.
24 | #
25 | # Important for running:
26 | #
27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
28 | # noncompliant, but you have some other compliant shell such as ksh or
29 | # bash, then to run this script, type that shell name before the whole
30 | # command line, like:
31 | #
32 | # ksh Gradle
33 | #
34 | # Busybox and similar reduced shells will NOT work, because this script
35 | # requires all of these POSIX shell features:
36 | # * functions;
37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
39 | # * compound commands having a testable exit status, especially «case»;
40 | # * various built-in commands including «command», «set», and «ulimit».
41 | #
42 | # Important for patching:
43 | #
44 | # (2) This script targets any POSIX shell, so it avoids extensions provided
45 | # by Bash, Ksh, etc; in particular arrays are avoided.
46 | #
47 | # The "traditional" practice of packing multiple parameters into a
48 | # space-separated string is a well documented source of bugs and security
49 | # problems, so this is (mostly) avoided, by progressively accumulating
50 | # options in "$@", and eventually passing that to Java.
51 | #
52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
54 | # see the in-line comments for details.
55 | #
56 | # There are tweaks for specific operating systems such as AIX, CygWin,
57 | # Darwin, MinGW, and NonStop.
58 | #
59 | # (3) This script is generated from the Groovy template
60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
61 | # within the Gradle project.
62 | #
63 | # You can find Gradle at https://github.com/gradle/gradle/.
64 | #
65 | ##############################################################################
66 |
67 | # Attempt to set APP_HOME
68 |
69 | # Resolve links: $0 may be a link
70 | app_path=$0
71 |
72 | # Need this for daisy-chained symlinks.
73 | while
74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
75 | [ -h "$app_path" ]
76 | do
77 | ls=$( ls -ld "$app_path" )
78 | link=${ls#*' -> '}
79 | case $link in #(
80 | /*) app_path=$link ;; #(
81 | *) app_path=$APP_HOME$link ;;
82 | esac
83 | done
84 |
85 | # This is normally unused
86 | # shellcheck disable=SC2034
87 | APP_BASE_NAME=${0##*/}
88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
90 | ' "$PWD" ) || exit
91 |
92 | # Use the maximum available, or set MAX_FD != -1 to use that value.
93 | MAX_FD=maximum
94 |
95 | warn () {
96 | echo "$*"
97 | } >&2
98 |
99 | die () {
100 | echo
101 | echo "$*"
102 | echo
103 | exit 1
104 | } >&2
105 |
106 | # OS specific support (must be 'true' or 'false').
107 | cygwin=false
108 | msys=false
109 | darwin=false
110 | nonstop=false
111 | case "$( uname )" in #(
112 | CYGWIN* ) cygwin=true ;; #(
113 | Darwin* ) darwin=true ;; #(
114 | MSYS* | MINGW* ) msys=true ;; #(
115 | NONSTOP* ) nonstop=true ;;
116 | esac
117 |
118 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
119 |
120 |
121 | # Determine the Java command to use to start the JVM.
122 | if [ -n "$JAVA_HOME" ] ; then
123 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
124 | # IBM's JDK on AIX uses strange locations for the executables
125 | JAVACMD=$JAVA_HOME/jre/sh/java
126 | else
127 | JAVACMD=$JAVA_HOME/bin/java
128 | fi
129 | if [ ! -x "$JAVACMD" ] ; then
130 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
131 |
132 | Please set the JAVA_HOME variable in your environment to match the
133 | location of your Java installation."
134 | fi
135 | else
136 | JAVACMD=java
137 | if ! command -v java >/dev/null 2>&1
138 | then
139 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
140 |
141 | Please set the JAVA_HOME variable in your environment to match the
142 | location of your Java installation."
143 | fi
144 | fi
145 |
146 | # Increase the maximum file descriptors if we can.
147 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
148 | case $MAX_FD in #(
149 | max*)
150 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
151 | # shellcheck disable=SC2039,SC3045
152 | MAX_FD=$( ulimit -H -n ) ||
153 | warn "Could not query maximum file descriptor limit"
154 | esac
155 | case $MAX_FD in #(
156 | '' | soft) :;; #(
157 | *)
158 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
159 | # shellcheck disable=SC2039,SC3045
160 | ulimit -n "$MAX_FD" ||
161 | warn "Could not set maximum file descriptor limit to $MAX_FD"
162 | esac
163 | fi
164 |
165 | # Collect all arguments for the java command, stacking in reverse order:
166 | # * args from the command line
167 | # * the main class name
168 | # * -classpath
169 | # * -D...appname settings
170 | # * --module-path (only if needed)
171 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
172 |
173 | # For Cygwin or MSYS, switch paths to Windows format before running java
174 | if "$cygwin" || "$msys" ; then
175 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
176 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
177 |
178 | JAVACMD=$( cygpath --unix "$JAVACMD" )
179 |
180 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
181 | for arg do
182 | if
183 | case $arg in #(
184 | -*) false ;; # don't mess with options #(
185 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
186 | [ -e "$t" ] ;; #(
187 | *) false ;;
188 | esac
189 | then
190 | arg=$( cygpath --path --ignore --mixed "$arg" )
191 | fi
192 | # Roll the args list around exactly as many times as the number of
193 | # args, so each arg winds up back in the position where it started, but
194 | # possibly modified.
195 | #
196 | # NB: a `for` loop captures its iteration list before it begins, so
197 | # changing the positional parameters here affects neither the number of
198 | # iterations, nor the values presented in `arg`.
199 | shift # remove old arg
200 | set -- "$@" "$arg" # push replacement arg
201 | done
202 | fi
203 |
204 |
205 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
206 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
207 |
208 | # Collect all arguments for the java command:
209 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
210 | # and any embedded shellness will be escaped.
211 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
212 | # treated as '${Hostname}' itself on the command line.
213 |
214 | set -- \
215 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
216 | -classpath "$CLASSPATH" \
217 | org.gradle.wrapper.GradleWrapperMain \
218 | "$@"
219 |
220 | # Stop when "xargs" is not available.
221 | if ! command -v xargs >/dev/null 2>&1
222 | then
223 | die "xargs is not available"
224 | fi
225 |
226 | # Use "xargs" to parse quoted args.
227 | #
228 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
229 | #
230 | # In Bash we could simply go:
231 | #
232 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
233 | # set -- "${ARGS[@]}" "$@"
234 | #
235 | # but POSIX shell has neither arrays nor command substitution, so instead we
236 | # post-process each arg (as a line of input to sed) to backslash-escape any
237 | # character that might be a shell metacharacter, then use eval to reverse
238 | # that process (while maintaining the separation between arguments), and wrap
239 | # the whole thing up as a single "set" statement.
240 | #
241 | # This will of course break if any of these variables contains a newline or
242 | # an unmatched quote.
243 | #
244 |
245 | eval "set -- $(
246 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
247 | xargs -n1 |
248 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
249 | tr '\n' ' '
250 | )" '"$@"'
251 |
252 | exec "$JAVACMD" "$@"
253 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
74 |
75 |
76 | @rem Execute Gradle
77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
78 |
79 | :end
80 | @rem End local scope for the variables with windows NT shell
81 | if %ERRORLEVEL% equ 0 goto mainEnd
82 |
83 | :fail
84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
85 | rem the _cmd.exe /c_ return code!
86 | set EXIT_CODE=%ERRORLEVEL%
87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
89 | exit /b %EXIT_CODE%
90 |
91 | :mainEnd
92 | if "%OS%"=="Windows_NT" endlocal
93 |
94 | :omega
95 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | google()
5 | mavenCentral()
6 | }
7 | }
8 | dependencyResolutionManagement {
9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
10 | repositories {
11 | google()
12 | mavenCentral()
13 | }
14 | }
15 | rootProject.name = "LINKa type"
16 | include ':app'
17 |
--------------------------------------------------------------------------------