From 4276c16a98156bbef86ec7b27503274458fc674e Mon Sep 17 00:00:00 2001
From: Kieran BW <41634689+FredHappyface@users.noreply.github.com>
Date: Thu, 3 Mar 2022 00:33:07 +0000
Subject: [PATCH] add help docs, refactor import and sending functionality
---
CHANGELOG.md | 2 +
HELP.md | 95 +++++++++++
README.md | 5 +
TUTORIAL.md | 14 +-
app/src/main/AndroidManifest.xml | 2 +-
.../fredhappyface/ewesticker/ImageKeyboard.kt | 125 ++-------------
.../fredhappyface/ewesticker/MainActivity.kt | 99 ++----------
.../ewesticker/StickerImporter.kt | 94 +++++++++++
.../fredhappyface/ewesticker/StickerSender.kt | 151 ++++++++++++++++++
.../com/fredhappyface/ewesticker/Toaster.kt | 17 +-
app/src/main/res/values-es/strings.xml | 1 +
app/src/main/res/values/strings.xml | 3 +-
12 files changed, 394 insertions(+), 214 deletions(-)
create mode 100644 HELP.md
create mode 100644 app/src/main/java/com/fredhappyface/ewesticker/StickerImporter.kt
create mode 100644 app/src/main/java/com/fredhappyface/ewesticker/StickerSender.kt
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7deabba..2bee6b2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,8 @@ patch-level version changes can be found in [commit messages](../../commits/mast
## Next_Ver - 2022/xx/xx
- New Feature: Improve error messages for the user per https://github.com/FredHappyface/Android.EweSticker/issues/39
+- New Feature: Add help (HELP.md) to provide guidance for error messages
+- Bugfix: Refactor in response bug found when investigating https://github.com/FredHappyface/Android.EweSticker/issues/37
- Bugfix: Back button now enabled in fresh install per https://github.com/FredHappyface/Android.EweSticker/issues/38
- Update navbar theme (dark/light rather than the app accent colour)
- Update dependencies
diff --git a/HELP.md b/HELP.md
new file mode 100644
index 0000000..5726ccf
--- /dev/null
+++ b/HELP.md
@@ -0,0 +1,95 @@
+
+
+# Help Guide
+
+Support is provided via GitHub issues, please note this is provided on a voluntary basis
+
+Please take a look at [Error Codes](#error-codes) first. This may provide some useful information
+for why you are getting a certain error code. If an issue is created that is answered by this section
+you'll likely be asked if you've read this :)
+
+- [Error Codes](#error-codes)
+ - [E031](#e031)
+ - [E032](#e032)
+ - [E033](#e033)
+ - [E040](#e040)
+ - [E041](#e041)
+ - [E050](#e050)
+- [Reach out](#reach-out)
+
+## Error Codes
+
+### E031
+Some stickers failed to import (some number imported). Max stickers reached
+
+This means that the total number of stickers that you are trying to import exceeds the
+maximum number of stickers supported by EweSticker. Try and import fewer stickers,
+see [Tutorial](/TUTORIAL.md)
+
+**NOTE:** that the maximum pack size is currently **128** and the total maximum number of stickers supported
+is **4096**
+
+If you feel strongly that the maximum limit should be increased, open an issue (use the
+'Question' template) and make a request - Be sure to explain why this would be useful. Simply saying
+'I want 20000 stickers!' will likely result in the issue being closed
+
+### E032
+Some stickers failed to import (some number imported). Max pack size reached
+
+This means that one of your sticker packs contains a number of stickers that exceeds the
+maximum pack size supported by EweSticker. Try splitting the pack up into smaller chunks,
+see [Tutorial](/TUTORIAL.md)
+
+**NOTE:** that the maximum pack size is currently **128** and the total maximum number of stickers supported
+is **4096**
+
+If you feel strongly that the maximum limit should be increased, open an issue (use the
+'Question' template) and make a request - Be sure to explain why this would be useful. Simply saying
+'I want 20000 stickers!' will likely result in the issue being closed
+
+### E033
+Some stickers failed to import (some number imported). Unsupported formats found
+
+This could be for a few reasons, perhaps you have a non sticker file in the sticker directory such
+as a document in the wrong place. Alternatively this may result in a seemingly valid sticker not being
+imported. Chances are that the sticker is not in a [supported format](/README.md#features).
+
+### E040
+(image type) not supported here
+
+The application you are using doesn't support a sticker format or the compat-format
+
+Unfortunately, nothing can be done by EweSticker to solve this, you may need to contact the application
+developer you are trying to send a sticker to
+
+### E041
+Unexpected IOException when converting sticker
+
+This is an unexpected error and happened when creating a compat-sticker to send to the application.
+Please open an issue and provide as much information as you can. E.g. Android Version, phone
+manufacturer, app you are trying to send the sticker in
+
+### E050
+IllegalStateException when switching packs. Try switching away from and back to EweSticker
+
+This sometimes happens if you leave EweSticker as the current keyboard and switch back to it. The best
+way to solve this is to tap the back button in the pack selector and switch back to EweSticker.
+Please open an issue and provide as much information as you can. E.g. Android Version, phone
+manufacturer, app you are trying to send the sticker in.
+
+## Reach out
+
+Support is provided via GitHub issues, please note this is provided on a voluntary basis
+
+you are therefore not entitled to free customer service (that is not to say that contributions/ issues and questions are not welcome - more reminding you that project maintainers are well within their rights to prioritize other issues).
+
+https://github.com/FredHappyface/.github/blob/master/SUPPORT.md provides a little more info
+from the types of support you can expect
+
+Please make sure to read https://github.com/FredHappyface/Android.EweSticker/issues/21 before
+opening an issue, this ay seem a bit grumpy but chances are I won't be able to help with your
+issue if you do not fill in the template provided
+
+To open a new issue click the following link: https://github.com/FredHappyface/Android.EweSticker/issues/new/choose
+
+**NOTE:** you will need to have a GitHub account to open issues (create one at https://github.com/signup)
diff --git a/README.md b/README.md
index cf9480a..8b8761d 100644
--- a/README.md
+++ b/README.md
@@ -16,6 +16,7 @@ Sticker-board for android inspired by uSticker (forked from woosticker).
- [Features](#features)
- [Screenshots](#screenshots)
- [How to use](#how-to-use)
+- [Help](#help)
- [Lint with](#lint-with)
- [Language Information](#language-information)
- [Kotlin and Android Version](#kotlin-and-android-version)
@@ -72,6 +73,10 @@ Sticker-board for android inspired by uSticker (forked from woosticker).
See the [Tutorial](/TUTORIAL.md) for more information.
+## Help
+
+See the [Help](/HELP.md) for more information.
+
## Lint with
```txt
diff --git a/TUTORIAL.md b/TUTORIAL.md
index 593a474..390a1d4 100644
--- a/TUTORIAL.md
+++ b/TUTORIAL.md
@@ -1,9 +1,18 @@
-
+
# Tutorial
See below for a step-by-step tutorial on how to use EweSticker with your existing
sticker collection.
+- [Step 1 - Create Sticker Directory (and transfer to device)](#step-1---create-sticker-directory-and-transfer-to-device)
+- [Step 2 - Download EweSticker](#step-2---download-ewesticker)
+ - [Get it on F-Droid](#get-it-on-f-droid)
+ - [Get it on Google Play](#get-it-on-google-play)
+ - [Download the APK](#download-the-apk)
+- [Step 3 - Select Directory with EweSticker (and wait...)](#step-3---select-directory-with-ewesticker-and-wait)
+- [Step 4 - Activate the keyboard](#step-4---activate-the-keyboard)
+- [Step 5 - Send Stickers in your favourite apps](#step-5---send-stickers-in-your-favourite-apps)
+
## Step 1 - Create Sticker Directory (and transfer to device)
@@ -23,6 +32,9 @@ The sticker directory has the following structure:
Then transfer this to your phone/ device. Plugging this into a PC is a pretty
convenient way to do this.
+**NOTE:** that the maximum pack size is currently **128** and the total maximum number of stickers supported
+is **4096**
+
## Step 2 - Download EweSticker
### Get it on F-Droid
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 6e07ee6..8d395da 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -8,7 +8,7 @@
android:label="@string/app_name"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning"
- android:dataExtractionRules="@xml/data_extraction_rules">
+ android:dataExtractionRules="@xml/data_extraction_rules" tools:targetApi="s">
+ private lateinit var stickerSender: StickerSender
// onCreateInputView
private lateinit var keyboardRoot: ViewGroup
@@ -83,7 +71,7 @@ class ImageKeyboard : InputMethodService() {
override fun onCreate() {
// Misc
super.onCreate()
- val scale = applicationContext.resources.displayMetrics.density
+ val scale = baseContext.resources.displayMetrics.density
// Setup coil
val imageLoader =
ImageLoader.Builder(baseContext)
@@ -112,7 +100,7 @@ class ImageKeyboard : InputMethodService() {
(this.sharedPreferences.getInt("iconSize", 80) * scale)
})
.toInt()
- this.toaster = Toaster(applicationContext)
+ this.toaster = Toaster(baseContext)
// Load Packs
this.loadedPacks = HashMap()
val packs =
@@ -145,7 +133,7 @@ class ImageKeyboard : InputMethodService() {
* @return View keyboardLayout
*/
override fun onCreateInputView(): View {
- val keyboardLayout = View.inflate(applicationContext, R.layout.keyboard_layout, null)
+ val keyboardLayout = View.inflate(baseContext, R.layout.keyboard_layout, null)
this.keyboardRoot = keyboardLayout.findViewById(R.id.keyboardRoot)
this.packsList = keyboardLayout.findViewById(R.id.packsList)
this.packContent = keyboardLayout.findViewById(R.id.packContent)
@@ -183,8 +171,15 @@ class ImageKeyboard : InputMethodService() {
* @param restarting
*/
override fun onStartInput(info: EditorInfo?, restarting: Boolean) {
- this.supportedMimes =
- Utils.getSupportedMimes().filter { isCommitContentSupported(info, it) }
+ this.stickerSender = StickerSender(
+ this.baseContext,
+ this.toaster,
+ this.internalDir,
+ this.currentInputConnection,
+ this.currentInputEditorInfo,
+ this.compatCache,
+ this.imageLoader
+ )
}
/** When leaving some input field update the caches */
@@ -197,91 +192,6 @@ class ImageKeyboard : InputMethodService() {
super.onFinishInput()
}
- /**
- * In the event that a mimetype is unsupported by a InputConnectionCompat (looking at you,
- * Signal) create a temporary png and send that. In the event that png is not supported, alert
- * the user.
- *
- * @param file: File
- */
- private suspend fun doFallbackCommitContent(file: File) {
- // PNG might not be supported
- if ("image/png" !in this.supportedMimes) {
- toaster.toast(getString(R.string.fallback_040, file.extension))
- return
- }
- // Create a new compatSticker and convert the sticker to png
- val compatStickerName = file.hashCode().toString()
- val compatSticker = File(this.internalDir, "__compatSticker__/$compatStickerName.png")
- if (!compatSticker.exists()) {
- // If the sticker doesn't exist then create
- compatSticker.parentFile?.mkdirs()
- try {
- val request =
- ImageRequest.Builder(baseContext)
- .data(file)
- .target { result ->
- val bitmap = result.toBitmap()
- bitmap.compress(
- Bitmap.CompressFormat.PNG, 90, FileOutputStream(compatSticker)
- )
- }
- .build()
- imageLoader.execute(request)
- } catch (ignore: IOException) {
- toaster.toast(getString(R.string.fallback_041))
- }
- }
- // Send the compatSticker!
- doCommitContent("image/png", compatSticker)
- // Remove old stickers
- val remSticker = this.compatCache.add(compatStickerName)
- remSticker?.let { File(this.internalDir, "__compatSticker__/$remSticker.png").delete() }
- }
-
- /**
- * Send a sticker file to a InputConnectionCompat
- *
- * @param mimeType String
- * @param file File
- */
- private fun doCommitContent(mimeType: String, file: File) {
- // ContentUri, ClipDescription, linkUri
- val inputContentInfoCompat =
- InputContentInfoCompat(
- FileProvider.getUriForFile(this, "com.fredhappyface.ewesticker.inputcontent", file),
- ClipDescription(file.name, arrayOf(mimeType)),
- null
- )
- // InputConnection, EditorInfo, InputContentInfoCompat, int flags, null opts
- InputConnectionCompat.commitContent(
- currentInputConnection,
- currentInputEditorInfo,
- inputContentInfoCompat,
- InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION,
- null
- )
- }
-
- /**
- * Check if the sticker is supported by the receiver
- *
- * @param editorInfo: EditorInfo - the editor/ receiver
- * @param mimeType: String - the image mimetype
- * @return boolean - is the mimetype supported?
- */
- private fun isCommitContentSupported(editorInfo: EditorInfo?, mimeType: String?): Boolean {
- editorInfo?.packageName ?: return false
- mimeType ?: return false
- currentInputConnection ?: return false
- EditorInfoCompat.getContentMimeTypes(editorInfo).forEach {
- if (ClipDescription.compareMimeTypes(mimeType, it)) {
- return true
- }
- }
- return false
- }
-
/**
* Swap the pack layout every time a pack is selected. If already cached use that otherwise
* create the pack layout
@@ -362,12 +272,7 @@ class ImageKeyboard : InputMethodService() {
imgButton.setOnClickListener {
val file = it.tag as File
this.recentCache.add(file.absolutePath)
- val stickerType = Utils.getMimeType(file)
- if (stickerType == null || stickerType !in this.supportedMimes) {
- CoroutineScope(Dispatchers.Main).launch { doFallbackCommitContent(file) }
- return@setOnClickListener
- }
- doCommitContent(stickerType, file)
+ stickerSender.sendSticker(file)
}
imgButton.setOnLongClickListener { view: View ->
val file = view.tag as File
@@ -415,7 +320,7 @@ class ImageKeyboard : InputMethodService() {
if (SDK_INT >= 28) {
this.switchToPreviousInputMethod()
} else {
- (applicationContext.getSystemService(INPUT_METHOD_SERVICE) as
+ (baseContext.getSystemService(INPUT_METHOD_SERVICE) as
InputMethodManager)
.showInputMethodPicker()
}
diff --git a/app/src/main/java/com/fredhappyface/ewesticker/MainActivity.kt b/app/src/main/java/com/fredhappyface/ewesticker/MainActivity.kt
index b2cff4e..9d271b3 100644
--- a/app/src/main/java/com/fredhappyface/ewesticker/MainActivity.kt
+++ b/app/src/main/java/com/fredhappyface/ewesticker/MainActivity.kt
@@ -3,7 +3,6 @@ package com.fredhappyface.ewesticker
import android.app.Activity
import android.content.Intent
import android.content.SharedPreferences
-import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.os.Looper
@@ -16,31 +15,18 @@ import android.widget.SeekBar.OnSeekBarChangeListener
import android.widget.TextView
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
-import androidx.documentfile.provider.DocumentFile
import androidx.preference.PreferenceManager
-import java.io.File
-import java.nio.file.Files
import java.util.*
import java.util.concurrent.Executors
-private const val MAX_FILES = 4096
-private const val MAX_PACK_SIZE = 128
/** MainActivity class inherits from the AppCompatActivity class - provides the settings view */
class MainActivity : AppCompatActivity() {
- // init
- private val supportedMimes = Utils.getSupportedMimes()
-
// onCreate
private lateinit var sharedPreferences: SharedPreferences
private lateinit var contextView: View
private lateinit var toaster: Toaster
- // importSticker(s)
- private var filesLeft = MAX_FILES
- private var packSizes: MutableMap = mutableMapOf()
- private var totalStickers = 0
-
/**
* Sets up content view, shared prefs, etc.
*
@@ -53,7 +39,7 @@ class MainActivity : AppCompatActivity() {
// Set late-init attrs
this.sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
this.contextView = findViewById(R.id.activityMainRoot)
- this.toaster = Toaster(applicationContext)
+ this.toaster = Toaster(baseContext)
refreshStickerDirPath()
// Update UI with config
seekBar(findViewById(R.id.iconsPerXSb), findViewById(R.id.iconsPerXLbl), "iconsPerX", 3)
@@ -72,13 +58,14 @@ class MainActivity : AppCompatActivity() {
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val editor = this.sharedPreferences.edit()
- editor.putString("stickerDirPath", result.data?.data.toString())
+ val stickerDirPath = result.data?.data.toString()
+ editor.putString("stickerDirPath", stickerDirPath)
editor.putString("lastUpdateDate", Calendar.getInstance().time.toString())
editor.putString("recentCache", "")
editor.putString("compatCache", "")
editor.apply()
refreshStickerDirPath()
- importStickers()
+ importStickers(stickerDirPath)
}
}
@@ -98,46 +85,14 @@ class MainActivity : AppCompatActivity() {
* @param view: View
*/
fun chooseDir(view: View) {
- this.filesLeft = MAX_FILES
- this.totalStickers = 0
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
chooseDirResultLauncher.launch(intent)
}
- /**
- * Copies stickers from source to internal storage
- *
- * @param sticker sticker to copy over
- *
- * @return 1 if sticker imported successfully else 0
- */
- private fun importSticker(sticker: DocumentFile) {
- // Exit if sticker is unsupported or if pack size > MAX_PACK_SIZE
- val parentDir = sticker.parentFile?.name ?: "__default__"
- val packSize = this.packSizes[parentDir] ?: 0
- if (packSize > MAX_PACK_SIZE) {
- this.toaster.setState(2); return
- }
- if (sticker.type !in this.supportedMimes) {
- this.toaster.setState(3); return
- }
- this.packSizes[parentDir] = packSize + 1
- // Copy sticker to app storage
- val destSticker = File(filesDir, "stickers/${parentDir}/${sticker.name}")
- destSticker.parentFile?.mkdirs()
- try {
- val inputStream = contentResolver.openInputStream(sticker.uri)
- Files.copy(inputStream, destSticker.toPath())
- inputStream?.close()
- } catch (e: java.lang.Exception) {
- }
- this.totalStickers++
- }
-
/** Import files from storage to internal directory */
- private fun importStickers() {
+ private fun importStickers(stickerDirPath: String) {
// Use worker thread because this takes several seconds
val executor = Executors.newSingleThreadExecutor()
val handler = Handler(Looper.getMainLooper())
@@ -147,30 +102,21 @@ class MainActivity : AppCompatActivity() {
val button = findViewByIdLinks"- Project: https://github.com/FredHappyface/Android.EweSticker
- Tutorial: https://github.com/FredHappyface/Android.EweSticker/blob/main/TUTORIAL.md
+- Help: https://github.com/FredHappyface/Android.EweSticker/blob/main/HELP.md
- License: https://github.com/FredHappyface/Android.EweSticker/blob/main/LICENSE.mdPreferences changed. Reload the keyboard for settings to apply