allow exporting clipboard items into a file
This commit is contained in:
parent
aea7b7bc55
commit
1c3fb0ee11
|
@ -8,6 +8,10 @@
|
||||||
android:name="android.permission.USE_FINGERPRINT"
|
android:name="android.permission.USE_FINGERPRINT"
|
||||||
tools:node="remove" />
|
tools:node="remove" />
|
||||||
|
|
||||||
|
<uses-permission
|
||||||
|
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||||
|
android:maxSdkVersion="28" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".App"
|
android:name=".App"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
|
|
@ -10,6 +10,7 @@ import android.view.MenuItem
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import com.simplemobiletools.commons.dialogs.ConfirmationAdvancedDialog
|
import com.simplemobiletools.commons.dialogs.ConfirmationAdvancedDialog
|
||||||
import com.simplemobiletools.commons.extensions.*
|
import com.simplemobiletools.commons.extensions.*
|
||||||
|
import com.simplemobiletools.commons.helpers.LICENSE_GSON
|
||||||
import com.simplemobiletools.commons.models.FAQItem
|
import com.simplemobiletools.commons.models.FAQItem
|
||||||
import com.simplemobiletools.keyboard.BuildConfig
|
import com.simplemobiletools.keyboard.BuildConfig
|
||||||
import com.simplemobiletools.keyboard.R
|
import com.simplemobiletools.keyboard.R
|
||||||
|
@ -62,7 +63,7 @@ class MainActivity : SimpleActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun launchAbout() {
|
private fun launchAbout() {
|
||||||
val licenses = 0
|
val licenses = LICENSE_GSON
|
||||||
|
|
||||||
val faqItems = arrayListOf(
|
val faqItems = arrayListOf(
|
||||||
FAQItem(R.string.faq_2_title_commons, R.string.faq_2_text_commons),
|
FAQItem(R.string.faq_2_title_commons, R.string.faq_2_text_commons),
|
||||||
|
|
|
@ -1,22 +1,29 @@
|
||||||
package com.simplemobiletools.keyboard.activities
|
package com.simplemobiletools.keyboard.activities
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import com.simplemobiletools.commons.extensions.beVisibleIf
|
import com.google.gson.Gson
|
||||||
import com.simplemobiletools.commons.extensions.getAdjustedPrimaryColor
|
import com.simplemobiletools.commons.extensions.*
|
||||||
import com.simplemobiletools.commons.extensions.underlineText
|
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE
|
||||||
import com.simplemobiletools.commons.extensions.updateTextColors
|
|
||||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||||
|
import com.simplemobiletools.commons.helpers.isQPlus
|
||||||
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
|
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
|
||||||
import com.simplemobiletools.keyboard.R
|
import com.simplemobiletools.keyboard.R
|
||||||
import com.simplemobiletools.keyboard.adapters.ClipsActivityAdapter
|
import com.simplemobiletools.keyboard.adapters.ClipsActivityAdapter
|
||||||
import com.simplemobiletools.keyboard.dialogs.AddOrEditClipDialog
|
import com.simplemobiletools.keyboard.dialogs.AddOrEditClipDialog
|
||||||
|
import com.simplemobiletools.keyboard.dialogs.ExportClipsDialog
|
||||||
import com.simplemobiletools.keyboard.extensions.clipsDB
|
import com.simplemobiletools.keyboard.extensions.clipsDB
|
||||||
|
import com.simplemobiletools.keyboard.extensions.config
|
||||||
import com.simplemobiletools.keyboard.models.Clip
|
import com.simplemobiletools.keyboard.models.Clip
|
||||||
import kotlinx.android.synthetic.main.activity_manage_clipboard_items.*
|
import kotlinx.android.synthetic.main.activity_manage_clipboard_items.*
|
||||||
|
import java.io.File
|
||||||
|
import java.io.OutputStream
|
||||||
|
|
||||||
class ManageClipboardItemsActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
class ManageClipboardItemsActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
||||||
|
private val PICK_EXPORT_CLIPS_INTENT = 21
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
@ -43,12 +50,26 @@ class ManageClipboardItemsActivity : SimpleActivity(), RefreshRecyclerViewListen
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.add_clipboard_item -> addOrEditClip()
|
R.id.add_clipboard_item -> addOrEditClip()
|
||||||
|
R.id.export_clips -> exportClips()
|
||||||
|
R.id.import_clips -> importClips()
|
||||||
else -> return super.onOptionsItemSelected(item)
|
else -> return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, resultData)
|
||||||
|
if (requestCode == PICK_EXPORT_CLIPS_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) {
|
||||||
|
val outputStream = contentResolver.openOutputStream(resultData.data!!)
|
||||||
|
exportClipsTo(outputStream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun refreshItems() {
|
||||||
|
updateClips()
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateClips() {
|
private fun updateClips() {
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
val clips = clipsDB.getClips().toMutableList() as ArrayList<Clip>
|
val clips = clipsDB.getClips().toMutableList() as ArrayList<Clip>
|
||||||
|
@ -72,7 +93,52 @@ class ManageClipboardItemsActivity : SimpleActivity(), RefreshRecyclerViewListen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun refreshItems() {
|
private fun exportClips() {
|
||||||
updateClips()
|
if (isQPlus()) {
|
||||||
|
ExportClipsDialog(this, config.lastExportedClipsFolder, true) { path, filename ->
|
||||||
|
Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
||||||
|
type = "text/plain"
|
||||||
|
putExtra(Intent.EXTRA_TITLE, filename)
|
||||||
|
addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
startActivityForResult(this, PICK_EXPORT_CLIPS_INTENT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handlePermission(PERMISSION_WRITE_STORAGE) {
|
||||||
|
if (it) {
|
||||||
|
ExportClipsDialog(this, config.lastExportedClipsFolder, false) { path, filename ->
|
||||||
|
val file = File(path)
|
||||||
|
getFileOutputStream(file.toFileDirItem(this), true) {
|
||||||
|
exportClipsTo(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun exportClipsTo(outputStream: OutputStream?) {
|
||||||
|
if (outputStream == null) {
|
||||||
|
toast(R.string.unknown_error_occurred)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ensureBackgroundThread {
|
||||||
|
val clips = clipsDB.getClips().map { it.value }
|
||||||
|
if (clips.isEmpty()) {
|
||||||
|
toast(R.string.no_entries_for_exporting)
|
||||||
|
return@ensureBackgroundThread
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val json = Gson().toJson(clips)
|
||||||
|
outputStream.bufferedWriter().use { out ->
|
||||||
|
out.write(json)
|
||||||
|
}
|
||||||
|
|
||||||
|
toast(R.string.exporting_successful)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun importClips() {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
package com.simplemobiletools.keyboard.dialogs
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||||
|
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
|
||||||
|
import com.simplemobiletools.commons.dialogs.FilePickerDialog
|
||||||
|
import com.simplemobiletools.commons.extensions.*
|
||||||
|
import com.simplemobiletools.keyboard.R
|
||||||
|
import com.simplemobiletools.keyboard.extensions.config
|
||||||
|
import kotlinx.android.synthetic.main.dialog_export_clips.view.*
|
||||||
|
|
||||||
|
class ExportClipsDialog(
|
||||||
|
val activity: BaseSimpleActivity, path: String, val hidePath: Boolean,
|
||||||
|
callback: (path: String, filename: String) -> Unit
|
||||||
|
) {
|
||||||
|
init {
|
||||||
|
var folder = if (path.isNotEmpty() && activity.getDoesFilePathExist(path)) {
|
||||||
|
path
|
||||||
|
} else {
|
||||||
|
activity.internalStoragePath
|
||||||
|
}
|
||||||
|
|
||||||
|
val view = activity.layoutInflater.inflate(R.layout.dialog_export_clips, null).apply {
|
||||||
|
export_clips_filename.setText("${activity.getString(R.string.app_launcher_name)}_${activity.getCurrentFormattedDateTime()}")
|
||||||
|
|
||||||
|
if (hidePath) {
|
||||||
|
export_clips_path_label.beGone()
|
||||||
|
export_clips_path.beGone()
|
||||||
|
} else {
|
||||||
|
export_clips_path.text = activity.humanizePath(folder)
|
||||||
|
export_clips_path.setOnClickListener {
|
||||||
|
FilePickerDialog(activity, folder, false, showFAB = true) {
|
||||||
|
export_clips_path.text = activity.humanizePath(it)
|
||||||
|
folder = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AlertDialog.Builder(activity)
|
||||||
|
.setPositiveButton(R.string.ok, null)
|
||||||
|
.setNegativeButton(R.string.cancel, null)
|
||||||
|
.create().apply {
|
||||||
|
activity.setupDialogStuff(view, this, R.string.export_clipboard_items) {
|
||||||
|
getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
||||||
|
val filename = view.export_clips_filename.value
|
||||||
|
if (filename.isEmpty()) {
|
||||||
|
activity.toast(R.string.filename_cannot_be_empty)
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
|
||||||
|
val newPath = "${folder.trimEnd('/')}/$filename"
|
||||||
|
if (!newPath.getFilenameFromPath().isAValidFilename()) {
|
||||||
|
activity.toast(R.string.filename_invalid_characters)
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
|
||||||
|
activity.config.lastExportedClipsFolder = folder
|
||||||
|
if (!hidePath && activity.getDoesFilePathExist(newPath)) {
|
||||||
|
val title = String.format(activity.getString(R.string.file_already_exists_overwrite), newPath.getFilenameFromPath())
|
||||||
|
ConfirmationDialog(activity, title) {
|
||||||
|
callback(newPath, filename)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
callback(newPath, filename)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,4 +15,8 @@ class Config(context: Context) : BaseConfig(context) {
|
||||||
var showPopupOnKeypress: Boolean
|
var showPopupOnKeypress: Boolean
|
||||||
get() = prefs.getBoolean(SHOW_POPUP_ON_KEYPRESS, true)
|
get() = prefs.getBoolean(SHOW_POPUP_ON_KEYPRESS, true)
|
||||||
set(showPopupOnKeypress) = prefs.edit().putBoolean(SHOW_POPUP_ON_KEYPRESS, showPopupOnKeypress).apply()
|
set(showPopupOnKeypress) = prefs.edit().putBoolean(SHOW_POPUP_ON_KEYPRESS, showPopupOnKeypress).apply()
|
||||||
|
|
||||||
|
var lastExportedClipsFolder: String
|
||||||
|
get() = prefs.getString(LAST_EXPORTED_CLIPS_FOLDER, "")!!
|
||||||
|
set(lastExportedClipsFolder) = prefs.edit().putString(LAST_EXPORTED_CLIPS_FOLDER, lastExportedClipsFolder).apply()
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ const val MAX_KEYS_PER_MINI_ROW = 5
|
||||||
// shared prefs
|
// shared prefs
|
||||||
const val VIBRATE_ON_KEYPRESS = "vibrate_on_keypress"
|
const val VIBRATE_ON_KEYPRESS = "vibrate_on_keypress"
|
||||||
const val SHOW_POPUP_ON_KEYPRESS = "show_popup_on_keypress"
|
const val SHOW_POPUP_ON_KEYPRESS = "show_popup_on_keypress"
|
||||||
|
const val LAST_EXPORTED_CLIPS_FOLDER = "last_exported_clips_folder"
|
||||||
|
|
||||||
// differentiate current and pinned clips at the keyboards' Clipboard section
|
// differentiate current and pinned clips at the keyboards' Clipboard section
|
||||||
const val ITEM_SECTION_LABEL = 0
|
const val ITEM_SECTION_LABEL = 0
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/export_clips_wrapper"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/export_clips_holder"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="@dimen/activity_margin"
|
||||||
|
android:paddingTop="@dimen/activity_margin"
|
||||||
|
android:paddingRight="@dimen/activity_margin">
|
||||||
|
|
||||||
|
<com.simplemobiletools.commons.views.MyTextView
|
||||||
|
android:id="@+id/export_clips_path_label"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/small_margin"
|
||||||
|
android:text="@string/path"
|
||||||
|
android:textSize="@dimen/smaller_text_size" />
|
||||||
|
|
||||||
|
<com.simplemobiletools.commons.views.MyTextView
|
||||||
|
android:id="@+id/export_clips_path"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="@dimen/small_margin"
|
||||||
|
android:paddingStart="@dimen/small_margin"
|
||||||
|
android:paddingTop="@dimen/small_margin"
|
||||||
|
android:paddingBottom="@dimen/activity_margin" />
|
||||||
|
|
||||||
|
<com.simplemobiletools.commons.views.MyTextInputLayout
|
||||||
|
android:id="@+id/export_clips_hint"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/filename_without_txt">
|
||||||
|
|
||||||
|
<com.simplemobiletools.commons.views.MyEditText
|
||||||
|
android:id="@+id/export_clips_filename"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="@dimen/activity_margin"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textCursorDrawable="@null"
|
||||||
|
android:textSize="@dimen/normal_text_size" />
|
||||||
|
|
||||||
|
</com.simplemobiletools.commons.views.MyTextInputLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
|
@ -6,4 +6,12 @@
|
||||||
android:icon="@drawable/ic_plus_vector"
|
android:icon="@drawable/ic_plus_vector"
|
||||||
android:title="@string/add_new_item"
|
android:title="@string/add_new_item"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/import_clips"
|
||||||
|
android:title="@string/import_clipboard_items"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/export_clips"
|
||||||
|
android:title="@string/export_clipboard_items"
|
||||||
|
app:showAsAction="never" />
|
||||||
</menu>
|
</menu>
|
||||||
|
|
Loading…
Reference in New Issue