From 9f0a6b617d1103bcbd72314fb5ab22aad16b0640 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Tue, 14 May 2019 13:03:20 +0530 Subject: [PATCH 01/51] GSoC project abstract --- gsoc/abstract.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 gsoc/abstract.txt diff --git a/gsoc/abstract.txt b/gsoc/abstract.txt new file mode 100644 index 000000000..454b6cadb --- /dev/null +++ b/gsoc/abstract.txt @@ -0,0 +1,14 @@ +New Features: + - Local sharing of ZIMs using WiFi: Enable users to share ZIM files locally using WiFi, allowing users to easily share ZIM files with each other without the need of a computer + - In-app Note Keeping: Inbuilt note keeper for each ZIM file, allowing users to jot down points from within the app itself + - Implement #765 (& specific-article sharing): Complete the issue and use the new structure to enable users to share articles with others (link to ZIM article for Kiwix users, URL for others) + - User Feedback activity: To submit feedback, modelled after the contact page of the website + +Enhancements: + - Navigational drawer based UI: Help centralise and use a single point of origin for the 3 main actions on the app (View library, Download wikis, Read wiki article) + - Categorisation of ZIMs in Library & Auto-hide system UI bars during reading + +Other details: + - Document all the code as I write it and fix bugs that I encounter along the way + - Weekly blog sharing my experience to generate interest in the project and open source contribution + - Take on additional bugs and issues if the above work gets finished before the final deadline From 1cd964c8e71cf3895e9c7f387c88217bdfb548d8 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Wed, 29 May 2019 17:07:51 +0530 Subject: [PATCH 02/51] Remove non-essential file (abstract.txt) --- gsoc/abstract.txt | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 gsoc/abstract.txt diff --git a/gsoc/abstract.txt b/gsoc/abstract.txt deleted file mode 100644 index 454b6cadb..000000000 --- a/gsoc/abstract.txt +++ /dev/null @@ -1,14 +0,0 @@ -New Features: - - Local sharing of ZIMs using WiFi: Enable users to share ZIM files locally using WiFi, allowing users to easily share ZIM files with each other without the need of a computer - - In-app Note Keeping: Inbuilt note keeper for each ZIM file, allowing users to jot down points from within the app itself - - Implement #765 (& specific-article sharing): Complete the issue and use the new structure to enable users to share articles with others (link to ZIM article for Kiwix users, URL for others) - - User Feedback activity: To submit feedback, modelled after the contact page of the website - -Enhancements: - - Navigational drawer based UI: Help centralise and use a single point of origin for the 3 main actions on the app (View library, Download wikis, Read wiki article) - - Categorisation of ZIMs in Library & Auto-hide system UI bars during reading - -Other details: - - Document all the code as I write it and fix bugs that I encounter along the way - - Weekly blog sharing my experience to generate interest in the project and open source contribution - - Take on additional bugs and issues if the above work gets finished before the final deadline From 5f8ba8f0389f808e1b643e085d311f11f9a2a5cf Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Tue, 14 May 2019 13:03:20 +0530 Subject: [PATCH 03/51] GSoC project abstract --- gsoc/abstract.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 gsoc/abstract.txt diff --git a/gsoc/abstract.txt b/gsoc/abstract.txt new file mode 100644 index 000000000..454b6cadb --- /dev/null +++ b/gsoc/abstract.txt @@ -0,0 +1,14 @@ +New Features: + - Local sharing of ZIMs using WiFi: Enable users to share ZIM files locally using WiFi, allowing users to easily share ZIM files with each other without the need of a computer + - In-app Note Keeping: Inbuilt note keeper for each ZIM file, allowing users to jot down points from within the app itself + - Implement #765 (& specific-article sharing): Complete the issue and use the new structure to enable users to share articles with others (link to ZIM article for Kiwix users, URL for others) + - User Feedback activity: To submit feedback, modelled after the contact page of the website + +Enhancements: + - Navigational drawer based UI: Help centralise and use a single point of origin for the 3 main actions on the app (View library, Download wikis, Read wiki article) + - Categorisation of ZIMs in Library & Auto-hide system UI bars during reading + +Other details: + - Document all the code as I write it and fix bugs that I encounter along the way + - Weekly blog sharing my experience to generate interest in the project and open source contribution + - Take on additional bugs and issues if the above work gets finished before the final deadline From 38f236b9f1b663fa0b41e3772f401823b77518f0 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Wed, 29 May 2019 17:07:51 +0530 Subject: [PATCH 04/51] Remove non-essential file (abstract.txt) --- gsoc/abstract.txt | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 gsoc/abstract.txt diff --git a/gsoc/abstract.txt b/gsoc/abstract.txt deleted file mode 100644 index 454b6cadb..000000000 --- a/gsoc/abstract.txt +++ /dev/null @@ -1,14 +0,0 @@ -New Features: - - Local sharing of ZIMs using WiFi: Enable users to share ZIM files locally using WiFi, allowing users to easily share ZIM files with each other without the need of a computer - - In-app Note Keeping: Inbuilt note keeper for each ZIM file, allowing users to jot down points from within the app itself - - Implement #765 (& specific-article sharing): Complete the issue and use the new structure to enable users to share articles with others (link to ZIM article for Kiwix users, URL for others) - - User Feedback activity: To submit feedback, modelled after the contact page of the website - -Enhancements: - - Navigational drawer based UI: Help centralise and use a single point of origin for the 3 main actions on the app (View library, Download wikis, Read wiki article) - - Categorisation of ZIMs in Library & Auto-hide system UI bars during reading - -Other details: - - Document all the code as I write it and fix bugs that I encounter along the way - - Weekly blog sharing my experience to generate interest in the project and open source contribution - - Take on additional bugs and issues if the above work gets finished before the final deadline From fc7b63621b3924d2546581e7f177febbe6be3e52 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Tue, 14 May 2019 13:03:20 +0530 Subject: [PATCH 05/51] GSoC project abstract --- gsoc/abstract.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 gsoc/abstract.txt diff --git a/gsoc/abstract.txt b/gsoc/abstract.txt new file mode 100644 index 000000000..454b6cadb --- /dev/null +++ b/gsoc/abstract.txt @@ -0,0 +1,14 @@ +New Features: + - Local sharing of ZIMs using WiFi: Enable users to share ZIM files locally using WiFi, allowing users to easily share ZIM files with each other without the need of a computer + - In-app Note Keeping: Inbuilt note keeper for each ZIM file, allowing users to jot down points from within the app itself + - Implement #765 (& specific-article sharing): Complete the issue and use the new structure to enable users to share articles with others (link to ZIM article for Kiwix users, URL for others) + - User Feedback activity: To submit feedback, modelled after the contact page of the website + +Enhancements: + - Navigational drawer based UI: Help centralise and use a single point of origin for the 3 main actions on the app (View library, Download wikis, Read wiki article) + - Categorisation of ZIMs in Library & Auto-hide system UI bars during reading + +Other details: + - Document all the code as I write it and fix bugs that I encounter along the way + - Weekly blog sharing my experience to generate interest in the project and open source contribution + - Take on additional bugs and issues if the above work gets finished before the final deadline From a11f1ed8e870826be21284f98adcd7d0cce1a48d Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Sat, 18 May 2019 23:32:22 +0530 Subject: [PATCH 06/51] File with implementation details for Note Keeper --- gsoc/NoteKeeper.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 gsoc/NoteKeeper.txt diff --git a/gsoc/NoteKeeper.txt b/gsoc/NoteKeeper.txt new file mode 100644 index 000000000..5274cb1d4 --- /dev/null +++ b/gsoc/NoteKeeper.txt @@ -0,0 +1,3 @@ +* UI as a full-screen dialog (as per material design guidelines) + +* Need to discuss back-end implementation \ No newline at end of file From 80d897dce4caa9d5bfb52fdc957a96e9d25f2623 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Tue, 21 May 2019 12:09:54 +0530 Subject: [PATCH 07/51] Basic UI Barebones UI for the Note Keeper ready, in the form of a fullscreen dialog Next: UI Enhancements and adding functionality to menu buttons (Save, Share) --- .../kiwix/kiwixmobile/main/AddNoteDialog.java | 82 ++++++++++++++ .../kiwix/kiwixmobile/main/MainActivity.java | 57 +++++++++- app/src/main/res/drawable/ic_add_note.xml | 9 ++ .../main/res/drawable/ic_close_white_24dp.xml | 2 +- app/src/main/res/drawable/ic_save.xml | 9 ++ app/src/main/res/layout/dialog_add_note.xml | 105 ++++++++++++++++++ .../main/res/menu/menu_add_note_dialog.xml | 15 +++ app/src/main/res/menu/menu_main.xml | 8 +- app/src/main/res/values/strings.xml | 2 + app/src/main/res/values/styles.xml | 14 +++ 10 files changed, 296 insertions(+), 7 deletions(-) create mode 100644 app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java create mode 100644 app/src/main/res/drawable/ic_add_note.xml create mode 100644 app/src/main/res/drawable/ic_save.xml create mode 100644 app/src/main/res/layout/dialog_add_note.xml create mode 100644 app/src/main/res/menu/menu_add_note_dialog.xml diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java new file mode 100644 index 000000000..90d34fd55 --- /dev/null +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -0,0 +1,82 @@ +package org.kiwix.kiwixmobile.main; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.FragmentTransaction; + +import org.kiwix.kiwixmobile.R; + +public class AddNoteDialog extends DialogFragment { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setStyle(DialogFragment.STYLE_NORMAL, R.style.AddNoteDialogStyle); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + View view = inflater.inflate(R.layout.dialog_add_note, container, false); + + Toolbar toolbar = view.findViewById(R.id.add_note_toolbar); + toolbar.setNavigationIcon(R.drawable.ic_close_white_24dp); + //toolbar.setNavigationOnClickListener(); + //toolbar.setOnMenuItemClickListener + toolbar.setTitle("Note"); + toolbar.inflateMenu(R.menu.menu_add_note_dialog); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Dialog dialog = getDialog(); + closeKeyboard(); + dialog.dismiss(); + } + }); + + return view; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + EditText addNoteEditText = view.findViewById(R.id.add_note_edit_text); + addNoteEditText.requestFocus(); + showKeyboard(); + } + + public void showKeyboard(){ + InputMethodManager inputMethodManager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); + } + + public void closeKeyboard(){ + InputMethodManager inputMethodManager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + inputMethodManager.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); + } + + @Override + public void onStart() { + super.onStart(); + + Dialog dialog = getDialog(); + if(dialog != null) { + int width = ViewGroup.LayoutParams.MATCH_PARENT; + int height = ViewGroup.LayoutParams.MATCH_PARENT; + dialog.getWindow().setLayout(width, height); + } + } +} diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java index 53f6c5e8b..2631eba39 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java @@ -21,6 +21,7 @@ package org.kiwix.kiwixmobile.main; import android.Manifest; import android.app.Activity; +import android.app.Dialog; import android.appwidget.AppWidgetManager; import android.content.ActivityNotFoundException; import android.content.ComponentName; @@ -44,6 +45,7 @@ import android.util.AttributeSet; import android.util.Log; import android.view.ActionMode; import android.view.KeyEvent; +import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -70,6 +72,9 @@ import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import androidx.core.view.GravityCompat; import androidx.drawerlayout.widget.DrawerLayout; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentTransaction; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -434,11 +439,7 @@ public class MainActivity extends BaseActivity implements WebViewCallback, hideTabSwitcher(); selectTab(position); - /* Bug Fix - * Issue #592 in which the navigational history of the previously open tab (WebView) was - * carried forward to the newly selected/opened tab; causing erroneous enabling of - * navigational buttons. - */ + /* Bug Fix #592 */ updateBottomToolbarArrowsAlpha(); } @@ -845,6 +846,19 @@ public class MainActivity extends BaseActivity implements WebViewCallback, compatCallback.showSoftInput(); break; + case R.id.menu_add_note: + /*TODO: Create fullscreen dialog for Note Keeper*/ + //Toast.makeText(getApplicationContext(), "Add Note", Toast.LENGTH_SHORT).show(); + FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); + Fragment prev = getSupportFragmentManager().findFragmentByTag("AddNoteDialog"); + if(prev != null) { + fragmentTransaction.remove(prev); + } + fragmentTransaction.addToBackStack(null); + AddNoteDialog dialog = new AddNoteDialog(); + dialog.show(fragmentTransaction, "AddNoteDialog"); //Adds to transaction and handles commit + break; + case R.id.menu_bookmarks_list: goToBookmarks(); break; @@ -1975,4 +1989,37 @@ public class MainActivity extends BaseActivity implements WebViewCallback, public boolean checkNull(View view) { return view != null; } + + /*public class AddNoteDialog extends DialogFragment { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setStyle(DialogFragment.STYLE_NORMAL, R.style.AddNoteDialogStyle); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + View view = inflater.inflate(R.layout.dialog_add_note, container, false); + + Toolbar toolbar = findViewById(R.id.toolbar); + toolbar.setNavigationIcon(R.drawable.ic_close_white_24dp); + //toolbar.setNavigationOnClickListener(); + toolbar.setTitle("Add Note"); + + return view; + } + + @Override + public void onStart() { + super.onStart(); + + Dialog dialog = getDialog(); + if(dialog != null) { + int width = ViewGroup.LayoutParams.MATCH_PARENT; + int height = ViewGroup.LayoutParams.MATCH_PARENT; + dialog.getWindow().setLayout(width, height); + } + } + }*/ } diff --git a/app/src/main/res/drawable/ic_add_note.xml b/app/src/main/res/drawable/ic_add_note.xml new file mode 100644 index 000000000..d6e151f22 --- /dev/null +++ b/app/src/main/res/drawable/ic_add_note.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_close_white_24dp.xml b/app/src/main/res/drawable/ic_close_white_24dp.xml index 4a1ffc298..6af45f517 100644 --- a/app/src/main/res/drawable/ic_close_white_24dp.xml +++ b/app/src/main/res/drawable/ic_close_white_24dp.xml @@ -1,6 +1,6 @@ diff --git a/app/src/main/res/drawable/ic_save.xml b/app/src/main/res/drawable/ic_save.xml new file mode 100644 index 000000000..3a06e8a60 --- /dev/null +++ b/app/src/main/res/drawable/ic_save.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/dialog_add_note.xml b/app/src/main/res/layout/dialog_add_note.xml new file mode 100644 index 000000000..03434394c --- /dev/null +++ b/app/src/main/res/layout/dialog_add_note.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/menu/menu_add_note_dialog.xml b/app/src/main/res/menu/menu_add_note_dialog.xml new file mode 100644 index 000000000..37ba47112 --- /dev/null +++ b/app/src/main/res/menu/menu_add_note_dialog.xml @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml index 243fa7fca..627a4c734 100644 --- a/app/src/main/res/menu/menu_main.xml +++ b/app/src/main/res/menu/menu_main.xml @@ -6,7 +6,7 @@ android:icon="@drawable/action_search" android:title="@string/menu_search" android:visible="false" - app:showAsAction="ifRoom"/> + app:showAsAction="always"/> + + Switch tabs :D Close all tabs + Add Note + Save diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 7cdad26be..7e0366992 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -129,5 +129,19 @@ + + + From 9adeb988e75257647ff2be188808444b6733e908 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Tue, 21 May 2019 12:29:43 +0530 Subject: [PATCH 08/51] Update NoteKeeper.txt --- gsoc/NoteKeeper.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gsoc/NoteKeeper.txt b/gsoc/NoteKeeper.txt index 5274cb1d4..d3401ea92 100644 --- a/gsoc/NoteKeeper.txt +++ b/gsoc/NoteKeeper.txt @@ -1,3 +1,8 @@ * UI as a full-screen dialog (as per material design guidelines) +* Need to discuss back-end implementation -* Need to discuss back-end implementation \ No newline at end of file +Implementation: +- For changed file, ask user confirmation before closing on dismiss +- Disable save button for empty note files (as per Material Design)? +- Material Design says use only one confirmation action on top right - Shift 'Share' to content area +- Use MD guidelines for visual appearance and spacing \ No newline at end of file From 1394b97cff804e9882484987450a8372fa70267a Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Thu, 23 May 2019 11:34:02 +0530 Subject: [PATCH 09/51] Minor UI improvements + Update NoteKeeper.txt --- .../kiwix/kiwixmobile/main/AddNoteDialog.java | 39 ++++- app/src/main/res/layout/dialog_add_note.xml | 143 ++++++++++++------ gsoc/NoteKeeper.txt | 10 +- 3 files changed, 141 insertions(+), 51 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index 90d34fd55..8f8409d2f 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -4,11 +4,13 @@ import android.app.Dialog; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -36,7 +38,6 @@ public class AddNoteDialog extends DialogFragment { //toolbar.setNavigationOnClickListener(); //toolbar.setOnMenuItemClickListener toolbar.setTitle("Note"); - toolbar.inflateMenu(R.menu.menu_add_note_dialog); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -45,6 +46,25 @@ public class AddNoteDialog extends DialogFragment { dialog.dismiss(); } }); + toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + + switch (item.getItemId()) { + case R.id.share_note: + Toast.makeText(getContext(), "Share Note", Toast.LENGTH_SHORT).show(); + break; + + case R.id.save_note: + Toast.makeText(getContext(), "Save Note", Toast.LENGTH_SHORT).show(); + break; + } + + toolbar.inflateMenu(R.menu.menu_add_note_dialog); + + return true; + } + }); return view; } @@ -79,4 +99,21 @@ public class AddNoteDialog extends DialogFragment { dialog.getWindow().setLayout(width, height); } } + + /*@Override + public boolean onOptionsItemSelected(MenuItem item) { + super.onOptionsItemSelected(item); + + switch (item.getItemId()) { + case R.id.share_note: + Toast.makeText(getContext(), "Share Note", Toast.LENGTH_SHORT).show(); + break; + + case R.id.save_note: + Toast.makeText(getContext(), "Save Note", Toast.LENGTH_SHORT).show(); + break; + } + + return true; + }*/ } diff --git a/app/src/main/res/layout/dialog_add_note.xml b/app/src/main/res/layout/dialog_add_note.xml index 03434394c..eaacb99ca 100644 --- a/app/src/main/res/layout/dialog_add_note.xml +++ b/app/src/main/res/layout/dialog_add_note.xml @@ -11,7 +11,6 @@ android:background="@color/white"> @@ -31,75 +30,125 @@ android:hint="Wiki Title" android:textColor="#000000" android:textColorHint="#000000" - android:textStyle="bold" - android:textSize="30sp" - android:padding="5dp"/> + android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5" + android:paddingTop="10dp" + android:paddingLeft="10dp" + android:paddingRight="10dp"/> + + + android:textColorHint="@color/textDarkTertiary"/> diff --git a/gsoc/NoteKeeper.txt b/gsoc/NoteKeeper.txt index d3401ea92..4b20a96e0 100644 --- a/gsoc/NoteKeeper.txt +++ b/gsoc/NoteKeeper.txt @@ -1,8 +1,12 @@ * UI as a full-screen dialog (as per material design guidelines) -* Need to discuss back-end implementation +* DONE: Need to discuss back-end implementation + - Separate note for each wiki article + - {Primary External Storage}/Kiwix/Notes/WikiName/ArticleName.txt Implementation: +- Initially focus on creating necessary path directory and saving - For changed file, ask user confirmation before closing on dismiss - Disable save button for empty note files (as per Material Design)? -- Material Design says use only one confirmation action on top right - Shift 'Share' to content area -- Use MD guidelines for visual appearance and spacing \ No newline at end of file +- Use MD guidelines for visual appearance and spacing +- FIXED: Material Design says use only one confirmation action on top right - Shift 'Share' to content area + > Two buttons isn't a violation. Eg: Reddit From f10dbdb0836008a3e4d8d6487f08d9e06b76185d Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Thu, 23 May 2019 12:42:20 +0530 Subject: [PATCH 10/51] Updated steps for implementing the feature --- .../org/kiwix/kiwixmobile/main/AddNoteDialog.java | 2 ++ gsoc/NoteKeeper.txt | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index 8f8409d2f..6d2575290 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -53,10 +53,12 @@ public class AddNoteDialog extends DialogFragment { switch (item.getItemId()) { case R.id.share_note: Toast.makeText(getContext(), "Share Note", Toast.LENGTH_SHORT).show(); + //TODO: Add app-chooser to intent for sharing note text file break; case R.id.save_note: Toast.makeText(getContext(), "Save Note", Toast.LENGTH_SHORT).show(); + //TODO: Add code for saving note text files break; } diff --git a/gsoc/NoteKeeper.txt b/gsoc/NoteKeeper.txt index 4b20a96e0..238d4b0ff 100644 --- a/gsoc/NoteKeeper.txt +++ b/gsoc/NoteKeeper.txt @@ -1,10 +1,23 @@ * UI as a full-screen dialog (as per material design guidelines) * DONE: Need to discuss back-end implementation - Separate note for each wiki article - - {Primary External Storage}/Kiwix/Notes/WikiName/ArticleName.txt + - {External Storage}/Kiwix/Notes/WikiName/ArticleName.txt + +Steps: +1) Create a public directory in external storage and save file +2) Modify code to create path/directories as per: {External Storage}/Kiwix/Notes/WikiName/ArticleName.txt +3) Code for reading file if it exists in the said directory (when AddNoteDialog opens) +4) Finally, + - For changed file, ask user confirmation before closing on dismiss + - Disable save button for empty note files + Implementation: - Initially focus on creating necessary path directory and saving + + When opening note only look for readablility (writability if doesn't exist) + When saving, then ask for writability and inform user if don't get it + - For changed file, ask user confirmation before closing on dismiss - Disable save button for empty note files (as per Material Design)? - Use MD guidelines for visual appearance and spacing From 6466d5cba4c4ef8bad31e6b5bdab31b60f0d42e4 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Thu, 23 May 2019 13:21:29 +0530 Subject: [PATCH 11/51] Bug Fix: Missing menu options in Add Note Dialog --- .../main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index 6d2575290..e1f0b6736 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -61,13 +61,12 @@ public class AddNoteDialog extends DialogFragment { //TODO: Add code for saving note text files break; } - - toolbar.inflateMenu(R.menu.menu_add_note_dialog); - return true; } }); + toolbar.inflateMenu(R.menu.menu_add_note_dialog); + return view; } From e0c51427073d023b397b017a27c330b61e086425 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Thu, 23 May 2019 13:38:07 +0530 Subject: [PATCH 12/51] Partial functionality for Save Note Added code for creating relevant folder (if it doesn't exist) as per: {External Storage}/Kiwix/Notes/ Next: Code for creating a text file in above directory from the entered note text --- .../kiwix/kiwixmobile/main/AddNoteDialog.java | 68 ++++++++++++++----- 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index e1f0b6736..dea1a481e 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -3,6 +3,8 @@ package org.kiwix.kiwixmobile.main; import android.app.Dialog; import android.content.Context; import android.os.Bundle; +import android.os.Environment; +import android.util.Log; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; @@ -21,7 +23,12 @@ import androidx.fragment.app.FragmentTransaction; import org.kiwix.kiwixmobile.R; +import java.io.File; + public class AddNoteDialog extends DialogFragment { + + private EditText addNoteEditText; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -33,6 +40,8 @@ public class AddNoteDialog extends DialogFragment { super.onCreateView(inflater, container, savedInstanceState); View view = inflater.inflate(R.layout.dialog_add_note, container, false); + addNoteEditText = view.findViewById(R.id.add_note_edit_text); + Toolbar toolbar = view.findViewById(R.id.add_note_toolbar); toolbar.setNavigationIcon(R.drawable.ic_close_white_24dp); //toolbar.setNavigationOnClickListener(); @@ -59,6 +68,7 @@ public class AddNoteDialog extends DialogFragment { case R.id.save_note: Toast.makeText(getContext(), "Save Note", Toast.LENGTH_SHORT).show(); //TODO: Add code for saving note text files + saveNote(addNoteEditText.getText().toString()); break; } return true; @@ -74,7 +84,6 @@ public class AddNoteDialog extends DialogFragment { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - EditText addNoteEditText = view.findViewById(R.id.add_note_edit_text); addNoteEditText.requestFocus(); showKeyboard(); } @@ -89,6 +98,46 @@ public class AddNoteDialog extends DialogFragment { inputMethodManager.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); } + private void saveNote(String noteText) { + + if(isExternalStorageWritable()) { + File notesFolder = new File(Environment.getExternalStorageDirectory() + "/Kiwix/Notes"); + boolean folderExists = true; + + if(!notesFolder.exists()) { + folderExists = notesFolder.mkdir(); + } + + if(folderExists) { + File noteFile = new File(notesFolder.getAbsolutePath(), "noteFile.txt"); + } else { + Toast.makeText(getContext(), "Error: Check log", Toast.LENGTH_SHORT).show(); + Log.d("AddNoteDialog", "Required folder doesn't exist/"); + } + } + else { + Toast.makeText(getContext(), "Error saving note: External storage now writable", Toast.LENGTH_LONG).show(); + } + + } + + public boolean isExternalStorageWritable() { + String state = Environment.getExternalStorageState(); + if(Environment.MEDIA_MOUNTED.equals(state)) { + return true; + } + return false; + } + + public boolean isExternalStorageReadable() { + String state = Environment.getExternalStorageState(); + if(Environment.MEDIA_MOUNTED.equals(state) + || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { + return true; + } + return false; + } + @Override public void onStart() { super.onStart(); @@ -100,21 +149,4 @@ public class AddNoteDialog extends DialogFragment { dialog.getWindow().setLayout(width, height); } } - - /*@Override - public boolean onOptionsItemSelected(MenuItem item) { - super.onOptionsItemSelected(item); - - switch (item.getItemId()) { - case R.id.share_note: - Toast.makeText(getContext(), "Share Note", Toast.LENGTH_SHORT).show(); - break; - - case R.id.save_note: - Toast.makeText(getContext(), "Save Note", Toast.LENGTH_SHORT).show(); - break; - } - - return true; - }*/ } From 38e8eddfb5b9f75c254e327c0349713e94a8c725 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Thu, 23 May 2019 16:10:12 +0530 Subject: [PATCH 13/51] Increment: Files now being saved at current directory --- .../org/kiwix/kiwixmobile/main/AddNoteDialog.java | 12 ++++++++++++ gsoc/NoteKeeper.txt | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index dea1a481e..d5c3e10cb 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -24,6 +24,8 @@ import androidx.fragment.app.FragmentTransaction; import org.kiwix.kiwixmobile.R; import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; public class AddNoteDialog extends DialogFragment { @@ -110,6 +112,16 @@ public class AddNoteDialog extends DialogFragment { if(folderExists) { File noteFile = new File(notesFolder.getAbsolutePath(), "noteFile.txt"); + + //TODO: Save file code + try { + FileOutputStream fileOutputStream = new FileOutputStream(noteFile); + fileOutputStream.write(noteText.getBytes()); + fileOutputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } else { Toast.makeText(getContext(), "Error: Check log", Toast.LENGTH_SHORT).show(); Log.d("AddNoteDialog", "Required folder doesn't exist/"); diff --git a/gsoc/NoteKeeper.txt b/gsoc/NoteKeeper.txt index 238d4b0ff..b324ef009 100644 --- a/gsoc/NoteKeeper.txt +++ b/gsoc/NoteKeeper.txt @@ -4,7 +4,7 @@ - {External Storage}/Kiwix/Notes/WikiName/ArticleName.txt Steps: -1) Create a public directory in external storage and save file +1) DONE: Create a public directory in external storage and save file 2) Modify code to create path/directories as per: {External Storage}/Kiwix/Notes/WikiName/ArticleName.txt 3) Code for reading file if it exists in the said directory (when AddNoteDialog opens) 4) Finally, From 9c6bafbf485e23da8d6f108a15157fcf3c545255 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Thu, 23 May 2019 17:28:54 +0530 Subject: [PATCH 14/51] Increment: Note files now saved in required manner Note files are now being saved as per: {External Storage}/Kiwix/Notes/WikiName/ArticleName.txt --- .../java/org/kiwix/kiwixmobile/main/AddNoteDialog.java | 9 +++++++-- gsoc/NoteKeeper.txt | 6 +++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index d5c3e10cb..e6645dab9 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -22,6 +22,7 @@ import androidx.fragment.app.DialogFragment; import androidx.fragment.app.FragmentTransaction; import org.kiwix.kiwixmobile.R; +import org.kiwix.kiwixmobile.data.ZimContentProvider; import java.io.File; import java.io.FileOutputStream; @@ -65,6 +66,10 @@ public class AddNoteDialog extends DialogFragment { case R.id.share_note: Toast.makeText(getContext(), "Share Note", Toast.LENGTH_SHORT).show(); //TODO: Add app-chooser to intent for sharing note text file + /*String message = "Parent Directory - "+ ZimContentProvider.getZimFileTitle() + + "\nSub Directory - " + ((MainActivity)getActivity()).getCurrentWebView().getTitle(); + addNoteEditText.setText(message);*/ + break; case R.id.save_note: @@ -103,7 +108,7 @@ public class AddNoteDialog extends DialogFragment { private void saveNote(String noteText) { if(isExternalStorageWritable()) { - File notesFolder = new File(Environment.getExternalStorageDirectory() + "/Kiwix/Notes"); + File notesFolder = new File(Environment.getExternalStorageDirectory() + "/Kiwix/Notes/" + ZimContentProvider.getZimFileTitle()); boolean folderExists = true; if(!notesFolder.exists()) { @@ -111,7 +116,7 @@ public class AddNoteDialog extends DialogFragment { } if(folderExists) { - File noteFile = new File(notesFolder.getAbsolutePath(), "noteFile.txt"); + File noteFile = new File(notesFolder.getAbsolutePath(), ((MainActivity)getActivity()).getCurrentWebView().getTitle() + ".txt"); //TODO: Save file code try { diff --git a/gsoc/NoteKeeper.txt b/gsoc/NoteKeeper.txt index b324ef009..a67c121e8 100644 --- a/gsoc/NoteKeeper.txt +++ b/gsoc/NoteKeeper.txt @@ -5,7 +5,7 @@ Steps: 1) DONE: Create a public directory in external storage and save file -2) Modify code to create path/directories as per: {External Storage}/Kiwix/Notes/WikiName/ArticleName.txt +2) DONE: Modify code to create path/directories as per: {External Storage}/Kiwix/Notes/WikiName/ArticleName.txt 3) Code for reading file if it exists in the said directory (when AddNoteDialog opens) 4) Finally, - For changed file, ask user confirmation before closing on dismiss @@ -23,3 +23,7 @@ Implementation: - Use MD guidelines for visual appearance and spacing - FIXED: Material Design says use only one confirmation action on top right - Shift 'Share' to content area > Two buttons isn't a violation. Eg: Reddit + + +Testing: +- Across multiple books, articles, tabs \ No newline at end of file From 21de8175de6f47536260a0dbce2219b877963c55 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Thu, 23 May 2019 17:46:34 +0530 Subject: [PATCH 15/51] Minor UI improvement Note dialog now displays the article title (in text view at top of note area) --- .../main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java | 4 ++++ app/src/main/res/layout/dialog_add_note.xml | 1 + 2 files changed, 5 insertions(+) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index e6645dab9..a91db1cf9 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -12,6 +12,7 @@ import android.view.ViewGroup; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; +import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; @@ -30,6 +31,7 @@ import java.io.IOException; public class AddNoteDialog extends DialogFragment { + private TextView addNoteTextView; private EditText addNoteEditText; @Override @@ -43,6 +45,8 @@ public class AddNoteDialog extends DialogFragment { super.onCreateView(inflater, container, savedInstanceState); View view = inflater.inflate(R.layout.dialog_add_note, container, false); + addNoteTextView = view.findViewById(R.id.add_note_text_view); + addNoteTextView.setText(((MainActivity)getActivity()).getCurrentWebView().getTitle()); addNoteEditText = view.findViewById(R.id.add_note_edit_text); Toolbar toolbar = view.findViewById(R.id.add_note_toolbar); diff --git a/app/src/main/res/layout/dialog_add_note.xml b/app/src/main/res/layout/dialog_add_note.xml index eaacb99ca..d025de82c 100644 --- a/app/src/main/res/layout/dialog_add_note.xml +++ b/app/src/main/res/layout/dialog_add_note.xml @@ -23,6 +23,7 @@ Date: Fri, 24 May 2019 19:41:30 +0530 Subject: [PATCH 16/51] Fix Bug: Note files not getting saved 1) Fixed procedure for saving notes on API level 23+ (Marshmallow onwards), which uses run-time permission checks (& grants) instead of install-time grants 2) Use mkdirs() instead of mkdir() {as the desired path may require creation of multiple directories} 3) Shifted constants from MainActivity.java to Constants.java --- .../kiwix/kiwixmobile/main/AddNoteDialog.java | 15 ++++- .../kiwix/kiwixmobile/main/MainActivity.java | 66 +++++++++++++++++-- .../kiwix/kiwixmobile/utils/Constants.java | 6 ++ 3 files changed, 80 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index a91db1cf9..6222f4dcc 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -1,7 +1,9 @@ package org.kiwix.kiwixmobile.main; +import android.Manifest; import android.app.Dialog; import android.content.Context; +import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Environment; import android.util.Log; @@ -19,6 +21,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; +import androidx.core.content.ContextCompat; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.FragmentTransaction; @@ -33,6 +36,7 @@ public class AddNoteDialog extends DialogFragment { private TextView addNoteTextView; private EditText addNoteEditText; + private final String TAG = "AddNoteDialog"; @Override public void onCreate(Bundle savedInstanceState) { @@ -112,11 +116,16 @@ public class AddNoteDialog extends DialogFragment { private void saveNote(String noteText) { if(isExternalStorageWritable()) { + + if(ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + Log.d(TAG, "WRITE_EXTERNAL_STORAGE permission not granted"); + } + File notesFolder = new File(Environment.getExternalStorageDirectory() + "/Kiwix/Notes/" + ZimContentProvider.getZimFileTitle()); boolean folderExists = true; if(!notesFolder.exists()) { - folderExists = notesFolder.mkdir(); + folderExists = notesFolder.mkdirs(); } if(folderExists) { @@ -132,8 +141,8 @@ public class AddNoteDialog extends DialogFragment { } } else { - Toast.makeText(getContext(), "Error: Check log", Toast.LENGTH_SHORT).show(); - Log.d("AddNoteDialog", "Required folder doesn't exist/"); + Toast.makeText(getContext(), "Error: Check logs", Toast.LENGTH_SHORT).show(); + Log.d(TAG, "Required folder doesn't exist"); } } else { diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java index 2631eba39..fec69f0ff 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java @@ -133,8 +133,11 @@ import static org.kiwix.kiwixmobile.utils.Constants.EXTRA_ZIM_FILE_2; import static org.kiwix.kiwixmobile.utils.Constants.PREF_KIWIX_MOBILE; import static org.kiwix.kiwixmobile.utils.Constants.REQUEST_FILE_SEARCH; import static org.kiwix.kiwixmobile.utils.Constants.REQUEST_FILE_SELECT; +import static org.kiwix.kiwixmobile.utils.Constants.REQUEST_HISTORY_ITEM_CHOSEN; import static org.kiwix.kiwixmobile.utils.Constants.REQUEST_PREFERENCES; +import static org.kiwix.kiwixmobile.utils.Constants.REQUEST_READ_STORAGE_PERMISSION; import static org.kiwix.kiwixmobile.utils.Constants.REQUEST_STORAGE_PERMISSION; +import static org.kiwix.kiwixmobile.utils.Constants.REQUEST_WRITE_STORAGE_PERMISSION; import static org.kiwix.kiwixmobile.utils.Constants.RESULT_HISTORY_CLEARED; import static org.kiwix.kiwixmobile.utils.Constants.RESULT_RESTART; import static org.kiwix.kiwixmobile.utils.Constants.TAG_CURRENT_ARTICLES; @@ -150,8 +153,6 @@ import static org.kiwix.kiwixmobile.utils.UpdateUtils.reformatProviderUrl; public class MainActivity extends BaseActivity implements WebViewCallback, MainContract.View, BooksAdapter.OnItemClickListener { - private static final int REQUEST_READ_STORAGE_PERMISSION = 2; - private static final int REQUEST_HISTORY_ITEM_CHOSEN = 99; private static final String NEW_TAB = "NEW_TAB"; private static final String HOME_URL = "file:///android_asset/home.html"; public static boolean isFullscreenOpened; @@ -849,14 +850,20 @@ public class MainActivity extends BaseActivity implements WebViewCallback, case R.id.menu_add_note: /*TODO: Create fullscreen dialog for Note Keeper*/ //Toast.makeText(getApplicationContext(), "Add Note", Toast.LENGTH_SHORT).show(); - FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); + + //TODO: Check for permissions + if(requestExternalStorageWritePermission()) { + showAddNoteDialog(); + } + + /*FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); Fragment prev = getSupportFragmentManager().findFragmentByTag("AddNoteDialog"); if(prev != null) { fragmentTransaction.remove(prev); } fragmentTransaction.addToBackStack(null); AddNoteDialog dialog = new AddNoteDialog(); - dialog.show(fragmentTransaction, "AddNoteDialog"); //Adds to transaction and handles commit + dialog.show(fragmentTransaction, "AddNoteDialog");*/ //Adds to transaction and handles commit break; case R.id.menu_bookmarks_list: @@ -918,6 +925,42 @@ public class MainActivity extends BaseActivity implements WebViewCallback, return super.onOptionsItemSelected(item); } + private void showAddNoteDialog() { + FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); + Fragment prev = getSupportFragmentManager().findFragmentByTag("AddNoteDialog"); + if(prev != null) { + fragmentTransaction.remove(prev); + } + fragmentTransaction.addToBackStack(null); + AddNoteDialog dialog = new AddNoteDialog(); + dialog.show(fragmentTransaction, "AddNoteDialog"); + } + + boolean requestExternalStorageWritePermission() { + if(Build.VERSION.SDK_INT >= 23) { + + if(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + return true; + + } else { + if(shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + /* Returns false if + * 1) User has previously checked on "Don't ask me again" + * 2) Permission disabled on device + **/ + Toast.makeText(getApplicationContext(), "Storage access is required for Notes", Toast.LENGTH_LONG).show(); + } + + requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_STORAGE_PERMISSION); + } + + } else { //For Android versions below Marshmallow 6.0 (API 23) + return true; //As already requested at install time + } + + return false; + } + @SuppressWarnings("SameReturnValue") @OnLongClick(R.id.bottom_toolbar_bookmark) boolean goToBookmarks() { @@ -1087,6 +1130,21 @@ public class MainActivity extends BaseActivity implements WebViewCallback, startActivity(intent); }).show(); } + break; + } + + case REQUEST_WRITE_STORAGE_PERMISSION: { + //TODO: Handle response + if(grantResults.length > 0 + && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + /** + * Since at present the request is being used strictly for the AddNoteDialog, + * thus the response to the permission being granted is simply opening the dialog*/ + showAddNoteDialog(); + } else { + Toast.makeText(getApplicationContext(), "Notes can't be used without access to storage", Toast.LENGTH_LONG); + } + break; } } } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/utils/Constants.java b/app/src/main/java/org/kiwix/kiwixmobile/utils/Constants.java index e2dbd7a89..9d9b34b3e 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/utils/Constants.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/utils/Constants.java @@ -30,6 +30,12 @@ public final class Constants { public static final int REQUEST_STORAGE_PERMISSION = 1; + public static final int REQUEST_READ_STORAGE_PERMISSION = 2; + + public static final int REQUEST_WRITE_STORAGE_PERMISSION = 3; + + public static final int REQUEST_HISTORY_ITEM_CHOSEN = 99; + public static final int REQUEST_FILE_SELECT = 1234; public static final int REQUEST_PREFERENCES = 1235; From 4437d45f5dbcdae3d425fd975f1fae79afc709ee Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Fri, 24 May 2019 20:47:21 +0530 Subject: [PATCH 17/51] Refactor to use variables for ZIM file and article titles --- .../org/kiwix/kiwixmobile/main/AddNoteDialog.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index 6222f4dcc..4c82e89f2 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -36,12 +36,18 @@ public class AddNoteDialog extends DialogFragment { private TextView addNoteTextView; private EditText addNoteEditText; + private String zimFileTitle; + private String articleTitle; + private final String TAG = "AddNoteDialog"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setStyle(DialogFragment.STYLE_NORMAL, R.style.AddNoteDialogStyle); + + zimFileTitle = ZimContentProvider.getZimFileTitle(); + articleTitle = ((MainActivity)getActivity()).getCurrentWebView().getTitle(); } @Override @@ -50,7 +56,7 @@ public class AddNoteDialog extends DialogFragment { View view = inflater.inflate(R.layout.dialog_add_note, container, false); addNoteTextView = view.findViewById(R.id.add_note_text_view); - addNoteTextView.setText(((MainActivity)getActivity()).getCurrentWebView().getTitle()); + addNoteTextView.setText(articleTitle); addNoteEditText = view.findViewById(R.id.add_note_edit_text); Toolbar toolbar = view.findViewById(R.id.add_note_toolbar); @@ -119,9 +125,10 @@ public class AddNoteDialog extends DialogFragment { if(ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { Log.d(TAG, "WRITE_EXTERNAL_STORAGE permission not granted"); + return; } - File notesFolder = new File(Environment.getExternalStorageDirectory() + "/Kiwix/Notes/" + ZimContentProvider.getZimFileTitle()); + File notesFolder = new File(Environment.getExternalStorageDirectory() + "/Kiwix/Notes/" + zimFileTitle); boolean folderExists = true; if(!notesFolder.exists()) { @@ -129,7 +136,7 @@ public class AddNoteDialog extends DialogFragment { } if(folderExists) { - File noteFile = new File(notesFolder.getAbsolutePath(), ((MainActivity)getActivity()).getCurrentWebView().getTitle() + ".txt"); + File noteFile = new File(notesFolder.getAbsolutePath(), articleTitle + ".txt"); //TODO: Save file code try { From d2132708540798c49ad33000cb3a5feac8e441c2 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Fri, 24 May 2019 21:21:15 +0530 Subject: [PATCH 18/51] Minor UI/UX improvements - Note area extends to the full screen, with added provision of scrolling for very long notes - Toast displays result of note file saving (successful or otherwise) --- .../kiwix/kiwixmobile/main/AddNoteDialog.java | 8 +- app/src/main/res/layout/dialog_add_note.xml | 113 +++++++++--------- app/src/main/res/values/strings.xml | 2 + 3 files changed, 65 insertions(+), 58 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index 4c82e89f2..bbddd4ae7 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -87,7 +87,6 @@ public class AddNoteDialog extends DialogFragment { break; case R.id.save_note: - Toast.makeText(getContext(), "Save Note", Toast.LENGTH_SHORT).show(); //TODO: Add code for saving note text files saveNote(addNoteEditText.getText().toString()); break; @@ -125,6 +124,7 @@ public class AddNoteDialog extends DialogFragment { if(ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { Log.d(TAG, "WRITE_EXTERNAL_STORAGE permission not granted"); + Toast.makeText(getContext(), "Note save unsuccessful", Toast.LENGTH_LONG); return; } @@ -143,17 +143,19 @@ public class AddNoteDialog extends DialogFragment { FileOutputStream fileOutputStream = new FileOutputStream(noteFile); fileOutputStream.write(noteText.getBytes()); fileOutputStream.close(); + Toast.makeText(getContext(), "Note saved", Toast.LENGTH_SHORT).show(); } catch (IOException e) { e.printStackTrace(); } } else { - Toast.makeText(getContext(), "Error: Check logs", Toast.LENGTH_SHORT).show(); + //Toast.makeText(getContext(), "Error: Check logs", Toast.LENGTH_SHORT).show(); + Toast.makeText(getContext(), "Note save unsuccessful", Toast.LENGTH_LONG); Log.d(TAG, "Required folder doesn't exist"); } } else { - Toast.makeText(getContext(), "Error saving note: External storage now writable", Toast.LENGTH_LONG).show(); + Toast.makeText(getContext(), "Error saving note:\nStorage not writable", Toast.LENGTH_LONG).show(); } } diff --git a/app/src/main/res/layout/dialog_add_note.xml b/app/src/main/res/layout/dialog_add_note.xml index d025de82c..f5c0d7048 100644 --- a/app/src/main/res/layout/dialog_add_note.xml +++ b/app/src/main/res/layout/dialog_add_note.xml @@ -1,70 +1,73 @@ - + android:background="#ffffff" + android:orientation="vertical"> + + + + + + + + + + android:layout_height="match_parent"> - + android:layout_height="wrap_content" + android:maxLines="1" + android:background="@android:color/transparent" + android:hint="@string/wiki_book_title" + android:textColor="#000000" + android:textColorHint="#000000" + android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5" + android:paddingTop="10dp" + android:paddingLeft="10dp" + android:paddingRight="10dp"/> - - + - - - - - - - + - + + + + diff --git a/gsoc/NoteKeeper.txt b/gsoc/NoteKeeper.txt index c9f6aaafd..c7b3d1200 100644 --- a/gsoc/NoteKeeper.txt +++ b/gsoc/NoteKeeper.txt @@ -8,7 +8,7 @@ Steps: 2) DONE: Modify code to create path/directories as per: {External Storage}/Kiwix/Notes/WikiName/ArticleName.txt 3) DONE: Code for reading file if it exists in the said directory (when AddNoteDialog opens) 4) Finally, - - For changed file, ask user confirmation before closing on dismiss + - DONE: For changed file, ask user confirmation before closing on dismiss - DONE: Disable save until note edited - Share functionality: App chooser for sharing note - Disable buttons for empty note files From 88dd7393004e5c14adb78eccbb548d28d9f06b65 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Mon, 27 May 2019 20:16:39 +0530 Subject: [PATCH 24/51] Update NoteKeeper.txt --- gsoc/NoteKeeper.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gsoc/NoteKeeper.txt b/gsoc/NoteKeeper.txt index c7b3d1200..bfefe20e9 100644 --- a/gsoc/NoteKeeper.txt +++ b/gsoc/NoteKeeper.txt @@ -12,6 +12,7 @@ Steps: - DONE: Disable save until note edited - Share functionality: App chooser for sharing note - Disable buttons for empty note files +5) Support for Night-Mode Implementation: @@ -30,6 +31,7 @@ Implementation: Testing: - Across multiple books, articles, tabs - Configuration change +- Once support added: In night mode SUBSEQUENT FEATURE: From f2b98845b6cf506056347df017771204b4e5edf0 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Mon, 27 May 2019 20:38:45 +0530 Subject: [PATCH 25/51] Increment: Toolbar menu items (share, save) disabled for empty note files --- .../kiwix/kiwixmobile/main/AddNoteDialog.java | 66 ++++++++++++------- gsoc/NoteKeeper.txt | 2 +- 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index 2d9f5077c..3d983a541 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -72,32 +72,8 @@ public class AddNoteDialog extends DialogFragment {//implements ConfirmationAler public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); View view = inflater.inflate(R.layout.dialog_add_note, container, false); - //addNoteDialog = getDialog(); - addNoteTextView = view.findViewById(R.id.add_note_text_view); - addNoteTextView.setText(articleTitle); - - addNoteEditText = view.findViewById(R.id.add_note_edit_text); - //TODO: Use displayNote() to show the previously saved note if it exists - displayNote(); - - addNoteEditText.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - noteEdited = true; - Toast.makeText(getContext(), "Text changed", Toast.LENGTH_SHORT).show(); - addNoteEditText.removeTextChangedListener(this); - enableMenuItems(); - } - - @Override - public void afterTextChanged(Editable s) {} - }); - toolbar = view.findViewById(R.id.add_note_toolbar); toolbar.setNavigationIcon(R.drawable.ic_close_white_24dp); //toolbar.setNavigationOnClickListener(); @@ -144,10 +120,34 @@ public class AddNoteDialog extends DialogFragment {//implements ConfirmationAler toolbar.inflateMenu(R.menu.menu_add_note_dialog); disableMenuItems(); + addNoteTextView = view.findViewById(R.id.add_note_text_view); + addNoteTextView.setText(articleTitle); + + addNoteEditText = view.findViewById(R.id.add_note_edit_text); + //TODO: Use displayNote() to show the previously saved note if it exists + displayNote(); + + addNoteEditText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + noteEdited = true; + Toast.makeText(getContext(), "Text changed", Toast.LENGTH_SHORT).show(); + addNoteEditText.removeTextChangedListener(this); + enableSaveNoteMenuItem(); + enableShareNoteMenuItem(); + } + + @Override + public void afterTextChanged(Editable s) {} + }); + return view; } - private void enableMenuItems() { + private void enableSaveNoteMenuItem() { if(toolbar.getMenu() != null) { MenuItem saveItem = toolbar.getMenu().findItem(R.id.save_note); saveItem.setEnabled(true); @@ -158,11 +158,25 @@ public class AddNoteDialog extends DialogFragment {//implements ConfirmationAler } } + private void enableShareNoteMenuItem() { + if(toolbar.getMenu() != null) { + MenuItem shareItem = toolbar.getMenu().findItem(R.id.share_note); + shareItem.setEnabled(true); + shareItem.getIcon().setAlpha(255); + + } else { + Log.d(TAG, "Toolbar without inflated menu"); + } + } + private void disableMenuItems() { if(toolbar.getMenu() != null) { MenuItem saveItem = toolbar.getMenu().findItem(R.id.save_note); + MenuItem shareItem = toolbar.getMenu().findItem(R.id.share_note); saveItem.setEnabled(false); + shareItem.setEnabled(false); saveItem.getIcon().setAlpha(130); + shareItem.getIcon().setAlpha(130); } else { Log.d(TAG, "Toolbar without inflated menu"); @@ -231,6 +245,7 @@ public class AddNoteDialog extends DialogFragment {//implements ConfirmationAler fileOutputStream.write(noteText.getBytes()); fileOutputStream.close(); Toast.makeText(getContext(), "Note saved", Toast.LENGTH_SHORT).show(); + noteEdited = false; } catch (IOException e) { e.printStackTrace(); } @@ -292,6 +307,7 @@ public class AddNoteDialog extends DialogFragment {//implements ConfirmationAler } addNoteEditText.setText(contents.toString()); + enableShareNoteMenuItem(); //return contents.toString(); diff --git a/gsoc/NoteKeeper.txt b/gsoc/NoteKeeper.txt index bfefe20e9..3d27c6dcc 100644 --- a/gsoc/NoteKeeper.txt +++ b/gsoc/NoteKeeper.txt @@ -11,7 +11,7 @@ Steps: - DONE: For changed file, ask user confirmation before closing on dismiss - DONE: Disable save until note edited - Share functionality: App chooser for sharing note - - Disable buttons for empty note files + - DONE: Disable buttons for empty note files 5) Support for Night-Mode From e83b47d6908ae580b3e3d20b3ead2eeabbd0ae0d Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Mon, 27 May 2019 20:41:10 +0530 Subject: [PATCH 26/51] Bugfixes: Note save & confirmation dialogs Fix in Previous commit: No confirmation dialog for saved notes Current fix: Keep listening for state changes beyond first save --- app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index 3d983a541..59c553e1b 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -135,7 +135,6 @@ public class AddNoteDialog extends DialogFragment {//implements ConfirmationAler public void onTextChanged(CharSequence s, int start, int before, int count) { noteEdited = true; Toast.makeText(getContext(), "Text changed", Toast.LENGTH_SHORT).show(); - addNoteEditText.removeTextChangedListener(this); enableSaveNoteMenuItem(); enableShareNoteMenuItem(); } From 17fb3c1aa0d9384a046cfdc87c1eb9b1c4847f43 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Mon, 27 May 2019 23:20:08 +0530 Subject: [PATCH 27/51] Increment: Added functionality to share note files The note text files (.txt) can now be shared using the share option on toolbar, via an app chooser --- .../kiwix/kiwixmobile/main/AddNoteDialog.java | 45 +++++++++++++++++++ gsoc/NoteKeeper.txt | 2 +- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index 59c553e1b..8192b7a31 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -4,7 +4,10 @@ import android.Manifest; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; +import android.content.Intent; import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.text.Editable; @@ -27,9 +30,11 @@ import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.core.content.ContextCompat; +import androidx.core.content.FileProvider; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.FragmentTransaction; +import org.kiwix.kiwixmobile.BuildConfig; import org.kiwix.kiwixmobile.R; import org.kiwix.kiwixmobile.data.ZimContentProvider; import org.kiwix.kiwixmobile.utils.files.FileUtils; @@ -106,6 +111,7 @@ public class AddNoteDialog extends DialogFragment {//implements ConfirmationAler case R.id.share_note: Toast.makeText(getContext(), "Share Note", Toast.LENGTH_SHORT).show(); //TODO: Add app-chooser to intent for sharing note text file + shareNote(); break; case R.id.save_note: @@ -323,6 +329,45 @@ public class AddNoteDialog extends DialogFragment {//implements ConfirmationAler //return null; } + private void shareNote() { + if(noteEdited) { + noteEdited = false; + saveNote(addNoteEditText.getText().toString()); + } + + File noteFile = new File(Environment.getExternalStorageDirectory() + "/Kiwix/Notes/" + zimFileTitle + "/" + articleTitle + ".txt"); + + Uri noteFileUri = null; + if(noteFile.exists()) { + + if (Build.VERSION.SDK_INT >= 24) { + noteFileUri = FileProvider.getUriForFile(getContext(), BuildConfig.APPLICATION_ID+".fileprovider", noteFile); + + } else { + noteFileUri = Uri.fromFile(noteFile); + } + + } else { + Toast.makeText(getContext(), "Note file doesn't exist", Toast.LENGTH_SHORT).show(); + } + + if(noteFileUri != null) { + Intent noteFileShareIntent = new Intent(Intent.ACTION_SEND); + //noteFileShareIntent.setDataAndType(noteFileUri, "text/plain"); + //noteFileShareIntent.setType("text/plain"); + noteFileShareIntent.setType("application/octet-stream"); + noteFileShareIntent.putExtra(Intent.EXTRA_STREAM, noteFileUri); + noteFileShareIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + Intent shareChooser = Intent.createChooser(noteFileShareIntent, "Share note file with:"); + Toast.makeText(getContext(), "Intent ready", Toast.LENGTH_SHORT).show(); + + if(noteFileShareIntent.resolveActivity(getActivity().getPackageManager()) != null) { + Toast.makeText(getContext(), "Starting activity", Toast.LENGTH_SHORT).show(); + startActivity(shareChooser); + } + } + } + public boolean isExternalStorageWritable() { String state = Environment.getExternalStorageState(); if(Environment.MEDIA_MOUNTED.equals(state)) { diff --git a/gsoc/NoteKeeper.txt b/gsoc/NoteKeeper.txt index 3d27c6dcc..0c1bf2808 100644 --- a/gsoc/NoteKeeper.txt +++ b/gsoc/NoteKeeper.txt @@ -10,7 +10,7 @@ Steps: 4) Finally, - DONE: For changed file, ask user confirmation before closing on dismiss - DONE: Disable save until note edited - - Share functionality: App chooser for sharing note + - DONE: Share functionality: App chooser for sharing note file - DONE: Disable buttons for empty note files 5) Support for Night-Mode From c5b94b5f220fa1be4aabd0479d60b5b64ac41284 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Mon, 27 May 2019 23:44:53 +0530 Subject: [PATCH 28/51] Minor UI improvement --- app/src/main/res/layout/dialog_add_note.xml | 12 ++++++------ gsoc/NoteKeeper.txt | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/src/main/res/layout/dialog_add_note.xml b/app/src/main/res/layout/dialog_add_note.xml index f5c0d7048..8f0963cde 100644 --- a/app/src/main/res/layout/dialog_add_note.xml +++ b/app/src/main/res/layout/dialog_add_note.xml @@ -38,14 +38,14 @@ android:textColorHint="#000000" android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5" android:paddingTop="10dp" - android:paddingLeft="10dp" - android:paddingRight="10dp"/> + android:paddingLeft="20dp" + android:paddingRight="20dp"/> Date: Tue, 28 May 2019 12:51:46 +0530 Subject: [PATCH 29/51] Increment: Added support for Night Mode --- .../kiwix/kiwixmobile/main/AddNoteDialog.java | 25 +++++++++++++++++-- app/src/main/res/layout/dialog_add_note.xml | 17 +++++++------ app/src/main/res/values/styles.xml | 19 ++++++++++++++ gsoc/NoteKeeper.txt | 3 ++- 4 files changed, 54 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index 8192b7a31..5e06c45d5 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -35,8 +35,10 @@ import androidx.fragment.app.DialogFragment; import androidx.fragment.app.FragmentTransaction; import org.kiwix.kiwixmobile.BuildConfig; +import org.kiwix.kiwixmobile.KiwixApplication; import org.kiwix.kiwixmobile.R; import org.kiwix.kiwixmobile.data.ZimContentProvider; +import org.kiwix.kiwixmobile.utils.SharedPreferenceUtil; import org.kiwix.kiwixmobile.utils.files.FileUtils; import java.io.BufferedReader; @@ -50,8 +52,12 @@ import java.io.UnsupportedEncodingException; import java.nio.CharBuffer; import java.nio.charset.StandardCharsets; +import javax.inject.Inject; + public class AddNoteDialog extends DialogFragment {//implements ConfirmationAlertDialogFragment.ConfirmationAlertDialogListener { + private SharedPreferenceUtil sharedPreferenceUtil = new SharedPreferenceUtil(KiwixApplication.getInstance()); + private Toolbar toolbar; private TextView addNoteTextView; private EditText addNoteEditText; @@ -67,7 +73,13 @@ public class AddNoteDialog extends DialogFragment {//implements ConfirmationAler @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setStyle(DialogFragment.STYLE_NORMAL, R.style.AddNoteDialogStyle); + + if(sharedPreferenceUtil != null && sharedPreferenceUtil.nightMode()) { + setStyle(DialogFragment.STYLE_NORMAL, R.style.AddNoteDialogStyle_Night); + Toast.makeText(getContext(), "Night Mode", Toast.LENGTH_SHORT).show(); + } else { + setStyle(DialogFragment.STYLE_NORMAL, R.style.AddNoteDialogStyle); + } zimFileTitle = ZimContentProvider.getZimFileTitle(); articleTitle = ((MainActivity)getActivity()).getCurrentWebView().getTitle(); @@ -415,6 +427,7 @@ class ConfirmationAlertDialogFragment extends DialogFragment { * AddNoteDialog with unsaved file changes **/ + private SharedPreferenceUtil sharedPreferenceUtil = new SharedPreferenceUtil(KiwixApplication.getInstance()); private Dialog addNoteDialog; public ConfirmationAlertDialogFragment(Dialog dialog) { @@ -443,7 +456,15 @@ class ConfirmationAlertDialogFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());//, R.style.ConfirmationAlertDialogStyle); + AlertDialog.Builder builder; + //, R.style.ConfirmationAlertDialogStyle); + if (sharedPreferenceUtil != null && sharedPreferenceUtil.nightMode()) { + builder = new AlertDialog.Builder(getActivity(), R.style.AppTheme_Dialog_Night); + Toast.makeText(getContext(), "Night Mode", Toast.LENGTH_SHORT).show(); + } else { + builder = new AlertDialog.Builder(getActivity()); + Toast.makeText(getContext(), "Light Mode", Toast.LENGTH_SHORT).show(); + } builder.setMessage("Discard unsaved changes?") .setPositiveButton("Yes", new DialogInterface.OnClickListener() { @Override diff --git a/app/src/main/res/layout/dialog_add_note.xml b/app/src/main/res/layout/dialog_add_note.xml index 8f0963cde..8308f563e 100644 --- a/app/src/main/res/layout/dialog_add_note.xml +++ b/app/src/main/res/layout/dialog_add_note.xml @@ -4,7 +4,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" - android:background="#ffffff" + android:background="@android:color/transparent" android:orientation="vertical"> + + + android:background="#000000"/> + android:hint="@string/note"/> + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 1c0ad06f8..3f1aa9344 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -134,6 +134,9 @@ true @color/primary_dark @color/primary + #000000 + #000000 + @color/textDarkTertiary false false @color/white @@ -143,6 +146,22 @@ --> + + - - + - - diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 3f1aa9344..3a2425c87 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -140,10 +140,6 @@ false false @color/white - - - - From a7f48d5168c7df5add344d5abcb15d855284e832 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Fri, 7 Jun 2019 13:46:49 +0530 Subject: [PATCH 37/51] Corrected string resource value for android:hint In the AddNoteDialog, use the correct value ("Wiki Article Title") instead of "Wiki Book Title" as the android:hint for the note heading --- app/src/main/res/layout/dialog_add_note.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/dialog_add_note.xml b/app/src/main/res/layout/dialog_add_note.xml index dccdcaf5d..508a401b8 100644 --- a/app/src/main/res/layout/dialog_add_note.xml +++ b/app/src/main/res/layout/dialog_add_note.xml @@ -32,7 +32,7 @@ android:layout_height="wrap_content" android:maxLines="1" android:background="@android:color/transparent" - android:hint="@string/wiki_book_title" + android:hint="@string/wiki_article_title" android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5" android:paddingTop="10dp" android:paddingLeft="20dp" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b0b2cbc96..d918ab03f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -248,7 +248,7 @@ Add Note Save Note - Wiki Book Title + Wiki Article Title Storage access is required for Notes Notes can\'t be used without access to storage Note save unsuccessful From b2df5b3d28f63c8718d0457358275cee6c81136a Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Fri, 7 Jun 2019 19:36:07 +0530 Subject: [PATCH 38/51] Bug fix: Added response to pressing Back button in AddNoteDialog In case of an edited note the 'Discard unsaved changes' dialog is displayed for the Back button (same response as is for the cross (X) on top of the dialog) --- .../kiwix/kiwixmobile/main/AddNoteDialog.java | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index d2a2968a9..33e78a5b1 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -90,16 +90,7 @@ public class AddNoteDialog extends DialogFragment { @Override public void onClick(View v) { closeKeyboard(); - if(noteEdited) { - // Custom AlertDialog for taking user confirmation before closing note dialog in case of unsaved changes - DialogFragment newFragment = new ConfirmationAlertDialogFragment(getDialog()); - newFragment.show(getActivity().getSupportFragmentManager(), "ConfirmationAlertDialog"); - - } else { - // Closing unedited note dialog straightaway - Dialog dialog = getDialog(); - dialog.dismiss(); - } + exitAddNoteDialog(); } }); @@ -149,6 +140,31 @@ public class AddNoteDialog extends DialogFragment { return view; } + // Override onBackPressed() to respond to user pressing 'Back' button on navigation bar + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + return new Dialog(getActivity(), getTheme()) { + @Override + public void onBackPressed() { + exitAddNoteDialog(); + } + }; + } + + private void exitAddNoteDialog() { + if(noteEdited) { + // Custom AlertDialog for taking user confirmation before closing note dialog in case of unsaved changes + DialogFragment newFragment = new ConfirmationAlertDialogFragment(getDialog()); + newFragment.show(getActivity().getSupportFragmentManager(), "ConfirmationAlertDialog"); + + } else { + // Closing unedited note dialog straightaway + Dialog dialog = getDialog(); + dialog.dismiss(); + } + } + private void disableMenuItems() { if(toolbar.getMenu() != null) { MenuItem saveItem = toolbar.getMenu().findItem(R.id.save_note); From 7ff8b672639b14c422daa0df3c6374419547ba71 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Mon, 10 Jun 2019 21:42:25 +0530 Subject: [PATCH 39/51] Increment: Feature to clear all notes Option to delete all notes and the folder itself from storage. Added in the menu options of MainActivity --- .../kiwix/kiwixmobile/main/AddNoteDialog.java | 2 +- .../kiwix/kiwixmobile/main/MainActivity.java | 48 +++++++++++++++++++ .../ic_baseline_delete_sweep_24px.xml | 9 ++++ app/src/main/res/menu/menu_main.xml | 6 +++ app/src/main/res/values/strings.xml | 1 + 5 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 app/src/main/res/drawable/ic_baseline_delete_sweep_24px.xml diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index 33e78a5b1..650cd2727 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -356,7 +356,7 @@ public class AddNoteDialog extends DialogFragment { } } - public boolean isExternalStorageWritable() { + public static boolean isExternalStorageWritable() { String state = Environment.getExternalStorageState(); if(Environment.MEDIA_MOUNTED.equals(state)) { return true; diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java index 51d11eec8..a1177dfdb 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java @@ -36,6 +36,7 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.CountDownTimer; +import android.os.Environment; import android.os.Handler; import android.provider.Settings; import android.text.SpannableString; @@ -851,6 +852,17 @@ public class MainActivity extends BaseActivity implements WebViewCallback, } break; + case R.id.menu_clear_notes: + if(requestExternalStorageWritePermissionForNotes()) { + // Check if notes available and clear all + if(clearAllNotes()) { + Toast.makeText(this, "Deleted entire folder", Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(this, "Not entirely deleted", Toast.LENGTH_SHORT).show(); + } + } + break; + case R.id.menu_bookmarks_list: goToBookmarks(); break; @@ -910,6 +922,42 @@ public class MainActivity extends BaseActivity implements WebViewCallback, return super.onOptionsItemSelected(item); } + private boolean clearAllNotes() { + boolean result = true; + + if(AddNoteDialog.isExternalStorageWritable()) { + if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + Log.d("MainActivity", "WRITE_EXTERNAL_STORAGE permission not granted"); + Toast.makeText(this, getString(R.string.note_save_unsuccessful), Toast.LENGTH_LONG); + return false; + } + + File notesParentFolder = new File(Environment.getExternalStorageDirectory() + "/Kiwix/Notes/"); + File[] childrenOfParentFolder = notesParentFolder.listFiles(); + + for(File wikiFileDirectory : childrenOfParentFolder) { + + if(wikiFileDirectory.isDirectory()) { + File[] notesInWikiDirectory = wikiFileDirectory.listFiles(); + + for(File noteFile : notesInWikiDirectory) { + + if(noteFile.isFile()) { + result = result && noteFile.delete(); + } + + } + } + + result = result && wikiFileDirectory.delete(); + } + + result = result && notesParentFolder.delete(); + } + + return result; + } + private void showAddNoteDialog() { // Creates the full screen AddNoteDialog, which is a DialogFragment FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); diff --git a/app/src/main/res/drawable/ic_baseline_delete_sweep_24px.xml b/app/src/main/res/drawable/ic_baseline_delete_sweep_24px.xml new file mode 100644 index 000000000..c5495c74c --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_delete_sweep_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml index 28df73db2..cad504d35 100644 --- a/app/src/main/res/menu/menu_main.xml +++ b/app/src/main/res/menu/menu_main.xml @@ -20,6 +20,12 @@ android:icon="@drawable/ic_add_note" app:showAsAction="always"/> + + Discard unsaved changes? Yes Cancel + Clear All Notes From c79aa8a9f9dc606b285bdd5526c95cfcbaf63ba0 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Wed, 12 Jun 2019 22:17:50 +0530 Subject: [PATCH 40/51] Increment: Confirmation dialog before deleting all notes + Documentation The 'Clear All Notes' option in the menu now shows a confirmation dialog for deleting all notes. Also added documentation for the feature. --- .../kiwix/kiwixmobile/main/MainActivity.java | 74 +++++++++++++------ app/src/main/res/values/strings.xml | 6 ++ 2 files changed, 58 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java index a1177dfdb..eeccff427 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java @@ -25,6 +25,7 @@ import android.appwidget.AppWidgetManager; import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; @@ -853,13 +854,8 @@ public class MainActivity extends BaseActivity implements WebViewCallback, break; case R.id.menu_clear_notes: - if(requestExternalStorageWritePermissionForNotes()) { - // Check if notes available and clear all - if(clearAllNotes()) { - Toast.makeText(this, "Deleted entire folder", Toast.LENGTH_SHORT).show(); - } else { - Toast.makeText(this, "Not entirely deleted", Toast.LENGTH_SHORT).show(); - } + if(requestExternalStorageWritePermissionForNotes()) { // Check permission since notes are stored in the public-external storage + showClearAllNotesDialog(); } break; @@ -922,44 +918,78 @@ public class MainActivity extends BaseActivity implements WebViewCallback, return super.onOptionsItemSelected(item); } - private boolean clearAllNotes() { - boolean result = true; + /** Dialog to take user confirmation before deleting all notes */ + private void showClearAllNotesDialog() { + + AlertDialog.Builder builder; + if (sharedPreferenceUtil != null && sharedPreferenceUtil.nightMode()) { // Night Mode support + builder = new AlertDialog.Builder(this, R.style.AppTheme_Dialog_Night); + } else { + builder = new AlertDialog.Builder(this); + } + + builder.setMessage(this.getString(R.string.delete_notes_confirmation_msg)) + .setNeutralButton(this.getString(R.string.dismiss), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // Do nothing + } + }) + .setPositiveButton(this.getString(R.string.delete), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + clearAllNotes(); + } + }) + .show(); + } + + /** Method to delete all user notes */ + private void clearAllNotes() { + + boolean result = true; // Result of all delete() calls is &&-ed to this variable if(AddNoteDialog.isExternalStorageWritable()) { if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { Log.d("MainActivity", "WRITE_EXTERNAL_STORAGE permission not granted"); - Toast.makeText(this, getString(R.string.note_save_unsuccessful), Toast.LENGTH_LONG); - return false; + Toast.makeText(this, this.getString(R.string.ext_storage_permission_not_granted), Toast.LENGTH_LONG); + return; } - File notesParentFolder = new File(Environment.getExternalStorageDirectory() + "/Kiwix/Notes/"); - File[] childrenOfParentFolder = notesParentFolder.listFiles(); + File notesDirectory = new File(Environment.getExternalStorageDirectory() + "/Kiwix/Notes/"); + File[] filesInNotesDirectory = notesDirectory.listFiles(); - for(File wikiFileDirectory : childrenOfParentFolder) { + if(filesInNotesDirectory == null) { // Notes folder doesn't exist + Toast.makeText(this, this.getString(R.string.notes_deletion_none_found), Toast.LENGTH_LONG).show(); + return; + } + for(File wikiFileDirectory : filesInNotesDirectory) { if(wikiFileDirectory.isDirectory()) { - File[] notesInWikiDirectory = wikiFileDirectory.listFiles(); - - for(File noteFile : notesInWikiDirectory) { + File[] filesInWikiDirectory = wikiFileDirectory.listFiles(); + for(File noteFile : filesInWikiDirectory) { if(noteFile.isFile()) { result = result && noteFile.delete(); } - } } - result = result && wikiFileDirectory.delete(); + result = result && wikiFileDirectory.delete(); // Wiki specific notes directory deleted } - result = result && notesParentFolder.delete(); + result = result && notesDirectory.delete(); // "{External Storage}/Kiwix/Notes" directory deleted } - return result; + if(result) { + Toast.makeText(this, this.getString(R.string.notes_deletion_successful), Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(this, this.getString(R.string.notes_deletion_unsuccessful), Toast.LENGTH_SHORT).show(); + } } + /** Creates the full screen AddNoteDialog, which is a DialogFragment */ private void showAddNoteDialog() { - // Creates the full screen AddNoteDialog, which is a DialogFragment FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); Fragment prev = getSupportFragmentManager().findFragmentByTag("AddNoteDialog"); if(prev != null) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f1b911b3e..77cfecf3c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -260,4 +260,10 @@ Yes Cancel Clear All Notes + Delete all notes? + Dismiss + Error: Storage permissions not granted + No notes found for deletion + Entire notes folder deleted + Some files not deleted From c4bd6a8ee3413a2cfab588d12e933fd7f135d591 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Fri, 14 Jun 2019 00:04:36 +0530 Subject: [PATCH 41/51] Increment: Use ConstraintLayout instead of LinearLayout as root view of AddNoteDialog --- app/src/main/res/layout/dialog_add_note.xml | 25 ++++++++++++++------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/app/src/main/res/layout/dialog_add_note.xml b/app/src/main/res/layout/dialog_add_note.xml index 508a401b8..4694d289e 100644 --- a/app/src/main/res/layout/dialog_add_note.xml +++ b/app/src/main/res/layout/dialog_add_note.xml @@ -1,14 +1,18 @@ - + android:background="@android:color/transparent"> + android:layout_height="wrap_content" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent"> + android:layout_width="0dp" + android:layout_height="0dp" + app:layout_constraintTop_toBottomOf="@id/app_bar_add_note_dialog" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent"> - + From 873eb2bce86c76b11962367701cb66bdf66b9f5e Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Sat, 15 Jun 2019 23:02:56 +0530 Subject: [PATCH 42/51] Refactor: Refer comments by @macgills in PR #1198 --- .../kiwix/kiwixmobile/main/AddNoteDialog.java | 34 ++++++------------- .../kiwix/kiwixmobile/main/MainActivity.java | 29 ++++++++-------- .../kiwix/kiwixmobile/utils/Constants.java | 5 +++ app/src/main/res/values/strings.xml | 4 +-- 4 files changed, 31 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index 650cd2727..5ea1c0e66 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -41,6 +41,8 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import static org.kiwix.kiwixmobile.utils.Constants.NOTES_DIRECTORY; + /** * Created by @Aditya-Sood (21/05/19) as a part of GSoC 2019 * @@ -68,11 +70,7 @@ public class AddNoteDialog extends DialogFragment { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if(sharedPreferenceUtil != null && sharedPreferenceUtil.nightMode()) { - setStyle(DialogFragment.STYLE_NORMAL, R.style.AddNoteDialogStyle_Night); // Night Mode support - } else { - setStyle(DialogFragment.STYLE_NORMAL, R.style.AddNoteDialogStyle); - } + setStyle(DialogFragment.STYLE_NORMAL, sharedPreferenceUtil.nightMode() ? R.style.AddNoteDialogStyle_Night : R.style.AddNoteDialogStyle); zimFileTitle = ZimContentProvider.getZimFileTitle(); articleTitle = ((MainActivity)getActivity()).getCurrentWebView().getTitle(); @@ -236,7 +234,7 @@ public class AddNoteDialog extends DialogFragment { return; } - File notesFolder = new File(Environment.getExternalStorageDirectory() + "/Kiwix/Notes/" + zimFileTitle); + File notesFolder = new File(NOTES_DIRECTORY + zimFileTitle); boolean folderExists = true; if(!notesFolder.exists()) { @@ -257,11 +255,11 @@ public class AddNoteDialog extends DialogFragment { } catch (IOException e) { e.printStackTrace(); - Toast.makeText(getContext(), getActivity().getString(R.string.note_save_unsuccessful), Toast.LENGTH_LONG); + Toast.makeText(this.getContext(), R.string.note_save_unsuccessful, Toast.LENGTH_LONG).show(); } } else { - Toast.makeText(getContext(), getActivity().getString(R.string.note_save_unsuccessful), Toast.LENGTH_LONG); + Toast.makeText(this.getContext(), R.string.note_save_unsuccessful, Toast.LENGTH_LONG).show(); Log.d(TAG, "Required folder doesn't exist"); } } @@ -278,7 +276,7 @@ public class AddNoteDialog extends DialogFragment { * is displayed in the EditText field (note content area) * */ - File noteFile = new File(Environment.getExternalStorageDirectory() + "/Kiwix/Notes/" + zimFileTitle + "/" + articleTitle + ".txt"); + File noteFile = new File(NOTES_DIRECTORY + zimFileTitle + "/" + articleTitle + ".txt"); if(noteFile.exists()) { noteFileExists = true; @@ -325,7 +323,7 @@ public class AddNoteDialog extends DialogFragment { saveNote(addNoteEditText.getText().toString()); // Save edited note before sharing the text file } - File noteFile = new File(Environment.getExternalStorageDirectory() + "/Kiwix/Notes/" + zimFileTitle + "/" + articleTitle + ".txt"); + File noteFile = new File(NOTES_DIRECTORY + zimFileTitle + "/" + articleTitle + ".txt"); Uri noteFileUri = null; if(noteFile.exists()) { @@ -357,12 +355,7 @@ public class AddNoteDialog extends DialogFragment { } public static boolean isExternalStorageWritable() { - String state = Environment.getExternalStorageState(); - if(Environment.MEDIA_MOUNTED.equals(state)) { - return true; - } else { - return false; - } + return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); } @Override @@ -407,19 +400,14 @@ class ConfirmationAlertDialogFragment extends DialogFragment { } builder.setMessage(getString(R.string.confirmation_alert_dialog_message)) - .setPositiveButton(getString(R.string.confirmation_alert_dialog_positive_btn), new DialogInterface.OnClickListener() { + .setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // User sure of discarding unsaved changes and closing note dialog addNoteDialog.dismiss(); } }) - .setNeutralButton(getString(R.string.confirmation_alert_dialog_neutral_btn), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - // No action to be taken in case of the neutral 'Cancel' action - } - }); + .setNegativeButton(getString(R.string.cancel), null); // Do nothing for 'Cancel' button return builder.create(); } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java index eeccff427..fb6140596 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java @@ -129,6 +129,7 @@ import static org.kiwix.kiwixmobile.utils.Constants.EXTRA_NOTIFICATION_ID; import static org.kiwix.kiwixmobile.utils.Constants.EXTRA_SEARCH; import static org.kiwix.kiwixmobile.utils.Constants.EXTRA_ZIM_FILE; import static org.kiwix.kiwixmobile.utils.Constants.EXTRA_ZIM_FILE_2; +import static org.kiwix.kiwixmobile.utils.Constants.NOTES_DIRECTORY; import static org.kiwix.kiwixmobile.utils.Constants.PREF_KIWIX_MOBILE; import static org.kiwix.kiwixmobile.utils.Constants.REQUEST_FILE_SEARCH; import static org.kiwix.kiwixmobile.utils.Constants.REQUEST_FILE_SELECT; @@ -929,13 +930,8 @@ public class MainActivity extends BaseActivity implements WebViewCallback, } builder.setMessage(this.getString(R.string.delete_notes_confirmation_msg)) - .setNeutralButton(this.getString(R.string.dismiss), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - // Do nothing - } - }) - .setPositiveButton(this.getString(R.string.delete), new DialogInterface.OnClickListener() { + .setNegativeButton(this.getString(R.string.cancel), null) // Do nothing for 'Cancel' button + .setPositiveButton(this.getString(R.string.yes), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { clearAllNotes(); @@ -956,7 +952,9 @@ public class MainActivity extends BaseActivity implements WebViewCallback, return; } - File notesDirectory = new File(Environment.getExternalStorageDirectory() + "/Kiwix/Notes/"); + // TODO: Replace below code with Kotlin's deleteRecursively() method + + File notesDirectory = new File(NOTES_DIRECTORY); File[] filesInNotesDirectory = notesDirectory.listFiles(); if(filesInNotesDirectory == null) { // Notes folder doesn't exist @@ -992,14 +990,15 @@ public class MainActivity extends BaseActivity implements WebViewCallback, private void showAddNoteDialog() { FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); Fragment prev = getSupportFragmentManager().findFragmentByTag("AddNoteDialog"); - if(prev != null) { - fragmentTransaction.remove(prev); // To prevent multiple instances of the DialogFragment - } - fragmentTransaction.addToBackStack(null); - AddNoteDialog dialogFragment = new AddNoteDialog(); - // For DialogFragments, show() handles the fragment commit and display - dialogFragment.show(fragmentTransaction, "AddNoteDialog"); + // To prevent multiple instances of the DialogFragment + if(prev != null) { + fragmentTransaction.show(prev); // For DialogFragments, show() handles the fragment commit and display + } else { + fragmentTransaction.addToBackStack(null); + AddNoteDialog dialogFragment = new AddNoteDialog(); + dialogFragment.show(fragmentTransaction, "AddNoteDialog"); + } } private boolean requestExternalStorageWritePermissionForNotes() { diff --git a/app/src/main/java/org/kiwix/kiwixmobile/utils/Constants.java b/app/src/main/java/org/kiwix/kiwixmobile/utils/Constants.java index af4306a34..64dd83e99 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/utils/Constants.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/utils/Constants.java @@ -17,6 +17,8 @@ */ package org.kiwix.kiwixmobile.utils; +import android.os.Environment; + import org.kiwix.kiwixmobile.BuildConfig; public final class Constants { @@ -136,4 +138,7 @@ public final class Constants { public static final String OLD_PROVIDER_DOMAIN = "org.kiwix.zim.base"; public static final String NEW_PROVIDER_DOMAIN = BuildConfig.APPLICATION_ID + ".zim.base"; + + // Path Constants + public static final String NOTES_DIRECTORY = Environment.getExternalStorageDirectory() + "/Kiwix/Notes/"; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 77cfecf3c..8e067d45f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -257,11 +257,9 @@ Note file doesn\'t exist Share note file with: Discard unsaved changes? - Yes - Cancel Clear All Notes Delete all notes? - Dismiss + Cancel Error: Storage permissions not granted No notes found for deletion Entire notes folder deleted From 11d3e8dea35efa578b74517567e9b87dc2f3228e Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Sun, 16 Jun 2019 19:22:13 +0530 Subject: [PATCH 43/51] Refactor: Use injection (Dagger) for SharedPreferenceUtil in AddNoteDialog --- .../di/components/ApplicationComponent.java | 3 +++ .../java/org/kiwix/kiwixmobile/main/AddNoteDialog.java | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java b/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java index a85fed50c..65a039749 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java @@ -28,6 +28,7 @@ import org.kiwix.kiwixmobile.di.modules.JNIModule; import org.kiwix.kiwixmobile.di.modules.NetworkModule; import org.kiwix.kiwixmobile.downloader.DownloadService; import org.kiwix.kiwixmobile.library.LibraryAdapter; +import org.kiwix.kiwixmobile.main.AddNoteDialog; import org.kiwix.kiwixmobile.main.KiwixWebView; import org.kiwix.kiwixmobile.search.AutoCompleteAdapter; import org.kiwix.kiwixmobile.settings.KiwixSettingsActivity; @@ -61,4 +62,6 @@ public interface ApplicationComponent { void inject(KiwixSettingsActivity.PrefsFragment prefsFragment); void inject(AutoCompleteAdapter autoCompleteAdapter); + + void inject(AddNoteDialog addNoteDialog); } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index 5ea1c0e66..f14d12f2f 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -41,6 +41,8 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import javax.inject.Inject; + import static org.kiwix.kiwixmobile.utils.Constants.NOTES_DIRECTORY; /** @@ -54,7 +56,8 @@ import static org.kiwix.kiwixmobile.utils.Constants.NOTES_DIRECTORY; public class AddNoteDialog extends DialogFragment { - private SharedPreferenceUtil sharedPreferenceUtil = new SharedPreferenceUtil(KiwixApplication.getInstance()); + @Inject + SharedPreferenceUtil sharedPreferenceUtil; private Toolbar toolbar; // Displays options for the note dialog private TextView addNoteTextView; // Displays article title @@ -66,6 +69,11 @@ public class AddNoteDialog extends DialogFragment { private final String TAG = "AddNoteDialog"; + public AddNoteDialog() { + super(); + KiwixApplication.getApplicationComponent().inject(this); + } + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); From 891cb950caacf6e187b8f15b38e4285df9af6256 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Sun, 16 Jun 2019 21:49:12 +0530 Subject: [PATCH 44/51] Refactor: Use ButterKnife to initialise views in AddNoteDialog --- .../kiwix/kiwixmobile/main/AddNoteDialog.java | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index f14d12f2f..f95f9d07e 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -43,10 +43,14 @@ import java.io.IOException; import javax.inject.Inject; +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.Unbinder; + import static org.kiwix.kiwixmobile.utils.Constants.NOTES_DIRECTORY; /** - * Created by @Aditya-Sood (21/05/19) as a part of GSoC 2019 + * Created by @author Aditya-Sood (21/05/19) as a part of GSoC 2019 * * AddNoteDialog extends DialogFragment and is used to display the note corresponding to a particular * article (of a particular zim file/wiki/book) as a full-screen dialog fragment. @@ -59,9 +63,15 @@ public class AddNoteDialog extends DialogFragment { @Inject SharedPreferenceUtil sharedPreferenceUtil; - private Toolbar toolbar; // Displays options for the note dialog - private TextView addNoteTextView; // Displays article title - private EditText addNoteEditText; // Displays zim file title (wiki name) + @BindView(R.id.add_note_toolbar) + Toolbar toolbar; // Displays options for the note dialog + @BindView(R.id.add_note_text_view) + TextView addNoteTextView; // Displays article title + @BindView(R.id.add_note_edit_text) + EditText addNoteEditText; // Displays zim file title (wiki name) + + private Unbinder unbinder; + private String zimFileTitle; private String articleTitle; private boolean noteFileExists = false; @@ -88,8 +98,8 @@ public class AddNoteDialog extends DialogFragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); View view = inflater.inflate(R.layout.dialog_add_note, container, false); + unbinder = ButterKnife.bind(this, view); - toolbar = view.findViewById(R.id.add_note_toolbar); toolbar.setTitle(getString(R.string.note)); toolbar.setNavigationIcon(R.drawable.ic_close_white_24dp); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @@ -121,10 +131,8 @@ public class AddNoteDialog extends DialogFragment { // 'Share' disabled for empty notes, 'Save' disabled for unedited notes disableMenuItems(); - addNoteTextView = view.findViewById(R.id.add_note_text_view); addNoteTextView.setText(articleTitle); - addNoteEditText = view.findViewById(R.id.add_note_edit_text); // Show the previously saved note if it exists displayNote(); @@ -378,6 +386,14 @@ public class AddNoteDialog extends DialogFragment { } } + @Override + public void onDestroyView() { + super.onDestroyView(); + if (unbinder != null) { + unbinder.unbind(); + } + } + } class ConfirmationAlertDialogFragment extends DialogFragment { From ffba82e0c79d0c539d55c336a9ae43416a71674e Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Thu, 20 Jun 2019 13:27:47 +0530 Subject: [PATCH 45/51] Refactor: Extract the display of all toasts (related to AddNoteDialog) to a common method showToast() --- .../kiwix/kiwixmobile/main/AddNoteDialog.java | 16 ++++++++++------ .../org/kiwix/kiwixmobile/main/MainActivity.java | 14 +++++++++----- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index f95f9d07e..240e24a35 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -246,7 +246,7 @@ public class AddNoteDialog extends DialogFragment { if(ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { Log.d(TAG, "WRITE_EXTERNAL_STORAGE permission not granted"); - Toast.makeText(getContext(), getString(R.string.note_save_unsuccessful), Toast.LENGTH_LONG); + showToast(R.string.note_save_unsuccessful, Toast.LENGTH_LONG); return; } @@ -266,21 +266,21 @@ public class AddNoteDialog extends DialogFragment { FileOutputStream fileOutputStream = new FileOutputStream(noteFile); fileOutputStream.write(noteText.getBytes()); fileOutputStream.close(); - Toast.makeText(getContext(), getActivity().getString(R.string.note_save_successful), Toast.LENGTH_SHORT).show(); + showToast(R.string.note_save_successful, Toast.LENGTH_SHORT); noteEdited = false; // As no unsaved changes remain } catch (IOException e) { e.printStackTrace(); - Toast.makeText(this.getContext(), R.string.note_save_unsuccessful, Toast.LENGTH_LONG).show(); + showToast(R.string.note_save_unsuccessful, Toast.LENGTH_LONG); } } else { - Toast.makeText(this.getContext(), R.string.note_save_unsuccessful, Toast.LENGTH_LONG).show(); + showToast(R.string.note_save_unsuccessful, Toast.LENGTH_LONG); Log.d(TAG, "Required folder doesn't exist"); } } else { - Toast.makeText(getContext(), getString(R.string.note_save_error_storage_not_writable), Toast.LENGTH_LONG).show(); + showToast(R.string.note_save_error_storage_not_writable, Toast.LENGTH_LONG); } } @@ -354,7 +354,7 @@ public class AddNoteDialog extends DialogFragment { } } else { - Toast.makeText(getContext(), getString(R.string.note_share_error_file_missing), Toast.LENGTH_SHORT).show(); + showToast(R.string.note_share_error_file_missing, Toast.LENGTH_SHORT); } if(noteFileUri != null) { @@ -374,6 +374,10 @@ public class AddNoteDialog extends DialogFragment { return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); } + private void showToast(int stringResource, int duration) { + Toast.makeText(getActivity(), stringResource, duration).show(); + } + @Override public void onStart() { super.onStart(); diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java index fb6140596..1ad4fc2e9 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java @@ -948,7 +948,7 @@ public class MainActivity extends BaseActivity implements WebViewCallback, if(AddNoteDialog.isExternalStorageWritable()) { if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { Log.d("MainActivity", "WRITE_EXTERNAL_STORAGE permission not granted"); - Toast.makeText(this, this.getString(R.string.ext_storage_permission_not_granted), Toast.LENGTH_LONG); + showToast(R.string.ext_storage_permission_not_granted, Toast.LENGTH_LONG); return; } @@ -958,7 +958,7 @@ public class MainActivity extends BaseActivity implements WebViewCallback, File[] filesInNotesDirectory = notesDirectory.listFiles(); if(filesInNotesDirectory == null) { // Notes folder doesn't exist - Toast.makeText(this, this.getString(R.string.notes_deletion_none_found), Toast.LENGTH_LONG).show(); + showToast(R.string.notes_deletion_none_found, Toast.LENGTH_LONG); return; } @@ -980,9 +980,9 @@ public class MainActivity extends BaseActivity implements WebViewCallback, } if(result) { - Toast.makeText(this, this.getString(R.string.notes_deletion_successful), Toast.LENGTH_SHORT).show(); + showToast(R.string.notes_deletion_successful, Toast.LENGTH_SHORT); } else { - Toast.makeText(this, this.getString(R.string.notes_deletion_unsuccessful), Toast.LENGTH_SHORT).show(); + showToast(R.string.notes_deletion_unsuccessful, Toast.LENGTH_SHORT); } } @@ -1013,7 +1013,7 @@ public class MainActivity extends BaseActivity implements WebViewCallback, * 1) User has previously checked on "Don't ask me again", and/or * 2) Permission has been disabled on device */ - Toast.makeText(getApplicationContext(), getString(R.string.ext_storage_permission_rationale_add_note), Toast.LENGTH_LONG).show(); + showToast(R.string.ext_storage_permission_rationale_add_note, Toast.LENGTH_LONG); } requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_STORAGE_PERMISSION_ADD_NOTE); @@ -1026,6 +1026,10 @@ public class MainActivity extends BaseActivity implements WebViewCallback, return false; } + private void showToast(int stringResource, int duration) { + Toast.makeText(this, stringResource, duration).show(); + } + @SuppressWarnings("SameReturnValue") @OnLongClick(R.id.bottom_toolbar_bookmark) boolean goToBookmarks() { From 7b8bd2b406b4b842166cf0f3937294fa97d35e94 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Thu, 20 Jun 2019 17:03:30 +0530 Subject: [PATCH 46/51] Refactor: Moved ConfirmationAlertDialogFragment to a separate file from AddNoteDialog ConfirmationAlertDialogFragment is now a generic helper class for displaying a 2-button (positive & negative) confirmation dialog fragment on top of an existing dialog fragment --- .../di/components/ApplicationComponent.java | 3 + .../kiwix/kiwixmobile/main/AddNoteDialog.java | 73 +++++----------- .../main/ConfirmationAlertDialogFragment.java | 85 +++++++++++++++++++ .../kiwix/kiwixmobile/main/MainActivity.java | 4 +- 4 files changed, 112 insertions(+), 53 deletions(-) create mode 100644 app/src/main/java/org/kiwix/kiwixmobile/main/ConfirmationAlertDialogFragment.java diff --git a/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java b/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java index 65a039749..1c99609f9 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java @@ -29,6 +29,7 @@ import org.kiwix.kiwixmobile.di.modules.NetworkModule; import org.kiwix.kiwixmobile.downloader.DownloadService; import org.kiwix.kiwixmobile.library.LibraryAdapter; import org.kiwix.kiwixmobile.main.AddNoteDialog; +import org.kiwix.kiwixmobile.main.ConfirmationAlertDialogFragment; import org.kiwix.kiwixmobile.main.KiwixWebView; import org.kiwix.kiwixmobile.search.AutoCompleteAdapter; import org.kiwix.kiwixmobile.settings.KiwixSettingsActivity; @@ -64,4 +65,6 @@ public interface ApplicationComponent { void inject(AutoCompleteAdapter autoCompleteAdapter); void inject(AddNoteDialog addNoteDialog); + + void inject(ConfirmationAlertDialogFragment confirmationAlertDialogFragment); } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index 240e24a35..cb67cee5b 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -3,7 +3,6 @@ package org.kiwix.kiwixmobile.main; import android.Manifest; import android.app.Dialog; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; @@ -24,7 +23,6 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.Toolbar; import androidx.core.content.ContextCompat; import androidx.core.content.FileProvider; @@ -58,7 +56,9 @@ import static org.kiwix.kiwixmobile.utils.Constants.NOTES_DIRECTORY; * Notes are saved as text files at location: "{External Storage}/Kiwix/Notes/ZimFileTitle/ArticleTitle.txt" * */ -public class AddNoteDialog extends DialogFragment { +public class AddNoteDialog extends DialogFragment implements ConfirmationAlertDialogFragment.UserClickListener { + + public static String TAG = "AddNoteDialog"; @Inject SharedPreferenceUtil sharedPreferenceUtil; @@ -77,8 +77,6 @@ public class AddNoteDialog extends DialogFragment { private boolean noteFileExists = false; private boolean noteEdited = false; // Keeps track of state of the note (whether edited since last save) - private final String TAG = "AddNoteDialog"; - public AddNoteDialog() { super(); KiwixApplication.getApplicationComponent().inject(this); @@ -169,13 +167,12 @@ public class AddNoteDialog extends DialogFragment { private void exitAddNoteDialog() { if(noteEdited) { // Custom AlertDialog for taking user confirmation before closing note dialog in case of unsaved changes - DialogFragment newFragment = new ConfirmationAlertDialogFragment(getDialog()); - newFragment.show(getActivity().getSupportFragmentManager(), "ConfirmationAlertDialog"); + DialogFragment newFragment = new ConfirmationAlertDialogFragment(TAG, R.string.confirmation_alert_dialog_message); + newFragment.show(getActivity().getSupportFragmentManager(), ConfirmationAlertDialogFragment.TAG); } else { // Closing unedited note dialog straightaway - Dialog dialog = getDialog(); - dialog.dismiss(); + dismissAddNoteDialog(); } } @@ -378,6 +375,22 @@ public class AddNoteDialog extends DialogFragment { Toast.makeText(getActivity(), stringResource, duration).show(); } + // Methods from ConfirmationAlertDialogFragment.UserClickListener interface + @Override + public void onPositiveClick() { + dismissAddNoteDialog(); + } + + @Override + public void onNegativeClick() { + // Do nothing + } + + private void dismissAddNoteDialog() { + Dialog dialog = getDialog(); + dialog.dismiss(); + } + @Override public void onStart() { super.onStart(); @@ -399,45 +412,3 @@ public class AddNoteDialog extends DialogFragment { } } - -class ConfirmationAlertDialogFragment extends DialogFragment { - /** - * Helper class to show the alert dialog in case the user tries to exit the - * AddNoteDialog with unsaved file changes - **/ - - private SharedPreferenceUtil sharedPreferenceUtil = new SharedPreferenceUtil(KiwixApplication.getInstance()); - private Dialog addNoteDialog; - - public ConfirmationAlertDialogFragment(Dialog dialog) { - super(); - addNoteDialog = dialog; - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - - AlertDialog.Builder builder; - - if (sharedPreferenceUtil != null && sharedPreferenceUtil.nightMode()) { - // Night Mode support - builder = new AlertDialog.Builder(getActivity(), R.style.AppTheme_Dialog_Night); - - } else { - builder = new AlertDialog.Builder(getActivity()); - - } - builder.setMessage(getString(R.string.confirmation_alert_dialog_message)) - .setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - // User sure of discarding unsaved changes and closing note dialog - addNoteDialog.dismiss(); - } - }) - .setNegativeButton(getString(R.string.cancel), null); // Do nothing for 'Cancel' button - - return builder.create(); - } - -} diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/ConfirmationAlertDialogFragment.java b/app/src/main/java/org/kiwix/kiwixmobile/main/ConfirmationAlertDialogFragment.java new file mode 100644 index 000000000..38220f7e2 --- /dev/null +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/ConfirmationAlertDialogFragment.java @@ -0,0 +1,85 @@ +package org.kiwix.kiwixmobile.main; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; + +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; + +import org.kiwix.kiwixmobile.KiwixApplication; +import org.kiwix.kiwixmobile.R; +import org.kiwix.kiwixmobile.utils.SharedPreferenceUtil; + +import javax.inject.Inject; + +/** + * Created by @Aditya-Sood as a part of GSoC 2019 + * + * This is a generic helper class for displaying a 2-button (positive & negative) confirmation dialog fragment on top of an existing dialog fragment + * - Only for confirmation dialogs with a Positive & Negative button + * - If you also need a Neutral button, add it selectively (if-else) for the required use case (Take care of the callback interface as well) + * + * Currently used as: + * - Helper class to show the alert dialog in case the user tries to exit the {@link AddNoteDialog} with unsaved file changes + * + **/ + +public class ConfirmationAlertDialogFragment extends DialogFragment { + + public static String TAG = "ConfirmationAlertDialog"; + @Inject SharedPreferenceUtil sharedPreferenceUtil; + private int stringResource; + private String parentDialogFragmentTAG; + + public ConfirmationAlertDialogFragment(String dialogFragmentTAG, int resourceId) { + super(); + parentDialogFragmentTAG = dialogFragmentTAG; + stringResource = resourceId; + KiwixApplication.getApplicationComponent().inject(this); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + Fragment parentDialogFragment = getFragmentManager().findFragmentByTag(parentDialogFragmentTAG); + + AlertDialog.Builder builder; + + if (sharedPreferenceUtil != null && sharedPreferenceUtil.nightMode()) { // Night Mode support + builder = new AlertDialog.Builder(getActivity(), R.style.AppTheme_Dialog_Night); + } else { + builder = new AlertDialog.Builder(getActivity()); + } + + builder.setMessage(stringResource) + .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + if(parentDialogFragment != null) { + ((UserClickListener) parentDialogFragment).onPositiveClick(); + } + } + }) + .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + if(parentDialogFragment != null) { + ((UserClickListener) parentDialogFragment).onNegativeClick(); + } + } + }); + + return builder.create(); + } + + /** Callback interface for responding to user clicks to a {@link ConfirmationAlertDialogFragment} dialog */ + public interface UserClickListener { + void onPositiveClick(); + + void onNegativeClick(); + } + +} diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java index 1ad4fc2e9..5cfc5f627 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java @@ -989,7 +989,7 @@ public class MainActivity extends BaseActivity implements WebViewCallback, /** Creates the full screen AddNoteDialog, which is a DialogFragment */ private void showAddNoteDialog() { FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); - Fragment prev = getSupportFragmentManager().findFragmentByTag("AddNoteDialog"); + Fragment prev = getSupportFragmentManager().findFragmentByTag(AddNoteDialog.TAG); // To prevent multiple instances of the DialogFragment if(prev != null) { @@ -997,7 +997,7 @@ public class MainActivity extends BaseActivity implements WebViewCallback, } else { fragmentTransaction.addToBackStack(null); AddNoteDialog dialogFragment = new AddNoteDialog(); - dialogFragment.show(fragmentTransaction, "AddNoteDialog"); + dialogFragment.show(fragmentTransaction, AddNoteDialog.TAG); } } From 77c30ac518ae9a2f872e6ca971917a64702ed323 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Thu, 20 Jun 2019 18:35:08 +0530 Subject: [PATCH 47/51] Refactor: Correct the use of string resources --- .../main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java | 2 +- .../kiwixmobile/main/ConfirmationAlertDialogFragment.java | 2 +- .../main/java/org/kiwix/kiwixmobile/main/MainActivity.java | 6 +++--- app/src/main/res/values/strings.xml | 1 - 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index cb67cee5b..bb12db433 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -98,7 +98,7 @@ public class AddNoteDialog extends DialogFragment implements ConfirmationAlertDi View view = inflater.inflate(R.layout.dialog_add_note, container, false); unbinder = ButterKnife.bind(this, view); - toolbar.setTitle(getString(R.string.note)); + toolbar.setTitle(R.string.note); toolbar.setNavigationIcon(R.drawable.ic_close_white_24dp); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/ConfirmationAlertDialogFragment.java b/app/src/main/java/org/kiwix/kiwixmobile/main/ConfirmationAlertDialogFragment.java index 38220f7e2..5119e5940 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/ConfirmationAlertDialogFragment.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/ConfirmationAlertDialogFragment.java @@ -53,7 +53,7 @@ public class ConfirmationAlertDialogFragment extends DialogFragment { } builder.setMessage(stringResource) - .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { + .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java index 5cfc5f627..5fa491778 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java @@ -929,9 +929,9 @@ public class MainActivity extends BaseActivity implements WebViewCallback, builder = new AlertDialog.Builder(this); } - builder.setMessage(this.getString(R.string.delete_notes_confirmation_msg)) - .setNegativeButton(this.getString(R.string.cancel), null) // Do nothing for 'Cancel' button - .setPositiveButton(this.getString(R.string.yes), new DialogInterface.OnClickListener() { + builder.setMessage(R.string.delete_notes_confirmation_msg) + .setNegativeButton(android.R.string.cancel, null) // Do nothing for 'Cancel' button + .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { clearAllNotes(); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8e067d45f..7905d34f1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -259,7 +259,6 @@ Discard unsaved changes? Clear All Notes Delete all notes? - Cancel Error: Storage permissions not granted No notes found for deletion Entire notes folder deleted From 62c46556229ae0bd3c4e27667545aed956ab0d68 Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Thu, 20 Jun 2019 21:22:26 +0530 Subject: [PATCH 48/51] Refactor: Avoid adding AddNoteDialog to back-stack and related code changes --- .../org/kiwix/kiwixmobile/main/AddNoteDialog.java | 11 ++++++++--- .../org/kiwix/kiwixmobile/main/MainActivity.java | 12 ++++++------ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index bb12db433..11e8e3cc6 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -27,6 +27,7 @@ import androidx.appcompat.widget.Toolbar; import androidx.core.content.ContextCompat; import androidx.core.content.FileProvider; import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; import org.kiwix.kiwixmobile.BuildConfig; import org.kiwix.kiwixmobile.KiwixApplication; @@ -166,9 +167,13 @@ public class AddNoteDialog extends DialogFragment implements ConfirmationAlertDi private void exitAddNoteDialog() { if(noteEdited) { - // Custom AlertDialog for taking user confirmation before closing note dialog in case of unsaved changes - DialogFragment newFragment = new ConfirmationAlertDialogFragment(TAG, R.string.confirmation_alert_dialog_message); - newFragment.show(getActivity().getSupportFragmentManager(), ConfirmationAlertDialogFragment.TAG); + Fragment previousInstance = getActivity().getSupportFragmentManager().findFragmentByTag(ConfirmationAlertDialogFragment.TAG); + + if(previousInstance == null) { + // Custom AlertDialog for taking user confirmation before closing note dialog in case of unsaved changes + DialogFragment newFragment = new ConfirmationAlertDialogFragment(TAG, R.string.confirmation_alert_dialog_message); + newFragment.show(getActivity().getSupportFragmentManager(), ConfirmationAlertDialogFragment.TAG); + } } else { // Closing unedited note dialog straightaway diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java index 5fa491778..7b622ba57 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java @@ -989,15 +989,15 @@ public class MainActivity extends BaseActivity implements WebViewCallback, /** Creates the full screen AddNoteDialog, which is a DialogFragment */ private void showAddNoteDialog() { FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); - Fragment prev = getSupportFragmentManager().findFragmentByTag(AddNoteDialog.TAG); + Fragment previousInstance = getSupportFragmentManager().findFragmentByTag(AddNoteDialog.TAG); // To prevent multiple instances of the DialogFragment - if(prev != null) { - fragmentTransaction.show(prev); // For DialogFragments, show() handles the fragment commit and display - } else { - fragmentTransaction.addToBackStack(null); + if(previousInstance == null) { + /* Since the DialogFragment is never added to the back-stack, so findFragmentByTag() + * returning null means that the AddNoteDialog is currently not on display (as doesn't exist) + **/ AddNoteDialog dialogFragment = new AddNoteDialog(); - dialogFragment.show(fragmentTransaction, AddNoteDialog.TAG); + dialogFragment.show(fragmentTransaction, AddNoteDialog.TAG); // For DialogFragments, show() handles the fragment commit and display } } From 5723554c53b11c0fd28f987cdb91962f01ee634d Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Thu, 20 Jun 2019 21:52:34 +0530 Subject: [PATCH 49/51] Refactor: Use Field-injection for SharedPreferenceUtil in AddNoteDialog and ConfirmationAlertDialogFragment * Replaced previously used constructor-injection with field-injection * Minor refactoring: Remove extra super() calls & use same names for constructor parameters as member variables --- .../di/components/ApplicationComponent.java | 3 --- .../kiwix/kiwixmobile/main/AddNoteDialog.java | 12 ++++-------- .../main/ConfirmationAlertDialogFragment.java | 18 ++++++++---------- .../kiwix/kiwixmobile/main/MainActivity.java | 2 +- 4 files changed, 13 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java b/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java index 1c99609f9..f51541de2 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java @@ -64,7 +64,4 @@ public interface ApplicationComponent { void inject(AutoCompleteAdapter autoCompleteAdapter); - void inject(AddNoteDialog addNoteDialog); - - void inject(ConfirmationAlertDialogFragment confirmationAlertDialogFragment); } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java index 11e8e3cc6..9faafd946 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/AddNoteDialog.java @@ -30,7 +30,6 @@ import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; import org.kiwix.kiwixmobile.BuildConfig; -import org.kiwix.kiwixmobile.KiwixApplication; import org.kiwix.kiwixmobile.R; import org.kiwix.kiwixmobile.data.ZimContentProvider; import org.kiwix.kiwixmobile.utils.SharedPreferenceUtil; @@ -40,7 +39,6 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import javax.inject.Inject; import butterknife.BindView; import butterknife.ButterKnife; @@ -61,8 +59,7 @@ public class AddNoteDialog extends DialogFragment implements ConfirmationAlertDi public static String TAG = "AddNoteDialog"; - @Inject - SharedPreferenceUtil sharedPreferenceUtil; + private SharedPreferenceUtil sharedPreferenceUtil; @BindView(R.id.add_note_toolbar) Toolbar toolbar; // Displays options for the note dialog @@ -78,9 +75,8 @@ public class AddNoteDialog extends DialogFragment implements ConfirmationAlertDi private boolean noteFileExists = false; private boolean noteEdited = false; // Keeps track of state of the note (whether edited since last save) - public AddNoteDialog() { - super(); - KiwixApplication.getApplicationComponent().inject(this); + public AddNoteDialog(SharedPreferenceUtil sharedPreferenceUtil) { + this.sharedPreferenceUtil = sharedPreferenceUtil; } @Override @@ -171,7 +167,7 @@ public class AddNoteDialog extends DialogFragment implements ConfirmationAlertDi if(previousInstance == null) { // Custom AlertDialog for taking user confirmation before closing note dialog in case of unsaved changes - DialogFragment newFragment = new ConfirmationAlertDialogFragment(TAG, R.string.confirmation_alert_dialog_message); + DialogFragment newFragment = new ConfirmationAlertDialogFragment(sharedPreferenceUtil, TAG, R.string.confirmation_alert_dialog_message); newFragment.show(getActivity().getSupportFragmentManager(), ConfirmationAlertDialogFragment.TAG); } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/ConfirmationAlertDialogFragment.java b/app/src/main/java/org/kiwix/kiwixmobile/main/ConfirmationAlertDialogFragment.java index 5119e5940..4680e1e68 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/ConfirmationAlertDialogFragment.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/ConfirmationAlertDialogFragment.java @@ -8,11 +8,9 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; -import org.kiwix.kiwixmobile.KiwixApplication; import org.kiwix.kiwixmobile.R; import org.kiwix.kiwixmobile.utils.SharedPreferenceUtil; -import javax.inject.Inject; /** * Created by @Aditya-Sood as a part of GSoC 2019 @@ -29,15 +27,15 @@ import javax.inject.Inject; public class ConfirmationAlertDialogFragment extends DialogFragment { public static String TAG = "ConfirmationAlertDialog"; - @Inject SharedPreferenceUtil sharedPreferenceUtil; - private int stringResource; + + private SharedPreferenceUtil sharedPreferenceUtil; + private int stringResourceId; private String parentDialogFragmentTAG; - public ConfirmationAlertDialogFragment(String dialogFragmentTAG, int resourceId) { - super(); - parentDialogFragmentTAG = dialogFragmentTAG; - stringResource = resourceId; - KiwixApplication.getApplicationComponent().inject(this); + public ConfirmationAlertDialogFragment(SharedPreferenceUtil sharedPreferenceUtil, String parentDialogFragmentTAG, int stringResourceId) { + this.sharedPreferenceUtil = sharedPreferenceUtil; + this.parentDialogFragmentTAG = parentDialogFragmentTAG; + this.stringResourceId = stringResourceId; } @Override @@ -52,7 +50,7 @@ public class ConfirmationAlertDialogFragment extends DialogFragment { builder = new AlertDialog.Builder(getActivity()); } - builder.setMessage(stringResource) + builder.setMessage(stringResourceId) .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java index 7b622ba57..e20c83fca 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/MainActivity.java @@ -996,7 +996,7 @@ public class MainActivity extends BaseActivity implements WebViewCallback, /* Since the DialogFragment is never added to the back-stack, so findFragmentByTag() * returning null means that the AddNoteDialog is currently not on display (as doesn't exist) **/ - AddNoteDialog dialogFragment = new AddNoteDialog(); + AddNoteDialog dialogFragment = new AddNoteDialog(sharedPreferenceUtil); dialogFragment.show(fragmentTransaction, AddNoteDialog.TAG); // For DialogFragments, show() handles the fragment commit and display } } From 50ad2e00d64bcf910a880117b5bb8dd3b5ded037 Mon Sep 17 00:00:00 2001 From: Kelson Date: Sat, 22 Jun 2019 07:55:42 +0200 Subject: [PATCH 50/51] Create FUNDING.yml --- .github/FUNDING.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..0244efe91 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: https://kiwix.org/support-us/ From 993dd3f9d004326cbbac6d33f8b34991fd531aca Mon Sep 17 00:00:00 2001 From: Aditya-Sood Date: Tue, 25 Jun 2019 16:53:38 +0530 Subject: [PATCH 51/51] Correct merging error --- .../kiwix/kiwixmobile/di/components/ApplicationComponent.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java b/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java index 90e5829a4..75f3629b2 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java @@ -32,9 +32,6 @@ import org.kiwix.kiwixmobile.main.KiwixWebView; import org.kiwix.kiwixmobile.search.AutoCompleteAdapter; import org.kiwix.kiwixmobile.settings.KiwixSettingsActivity; import org.kiwix.kiwixmobile.zim_manager.DownloadNotificationClickedReceiver; -import org.kiwix.kiwixmobile.library.LibraryAdapter; -import org.kiwix.kiwixmobile.main.AddNoteDialog; -import org.kiwix.kiwixmobile.main.ConfirmationAlertDialogFragment; @Singleton @Component(modules = {