Skip to content

Commit

Permalink
Merge branch 'standalone_keyboard_conversion'
Browse files Browse the repository at this point in the history
  • Loading branch information
Drakota committed Apr 8, 2021
2 parents 6c40684 + ce330f2 commit 8951a38
Show file tree
Hide file tree
Showing 42 changed files with 458 additions and 186 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
<p align="center" style="background: #0E0E10; border-radius: 10px; box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);">
<img src="./assets/images/banner.png" />
<img src="./images/banner.png" />
<a href="https://play.google.com/store/apps/details?id=com.drakota.bttvstickers&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1">
<img alt="Get it on Google Play" src="https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png" width="150px" />
</a>
</p>

<h4 align="center">
Search and discover BTTV emotes to add to your Gboard stickers and use them anywhere
Search and discover BTTV emotes to add to your keyboard stickers and use them anywhere
</h4>

## Features
- Sort emotes by top, trending, shared or global
- Search emotes by name
- Collect multiple emotes into a Gboard sticker pack
- Collect multiple emotes into a keyboard sticker pack
- Use the sticker pack to add the image of an emote anywhere that supports images (WhatsApp, Messenger, Telegram...)

## Screenshots
Expand All @@ -21,16 +21,16 @@ Search and discover BTTV emotes to add to your Gboard stickers and use them anyw
<table>
<tr>
<td style="text-align: center">
<img src="./assets/images/sc1.png" width="250" />
<img src="./images/screenshots/sc1.png" width="250" />
</td>
<td style="text-align: center">
<img src="./assets/images/sc2.png" width="250" />
<img src="./images/screenshots/sc2.png" width="250" />
</td>
<td style="text-align: center">
<img src="./assets/images/sc3.png" width="250" />
<img src="./images/screenshots/sc3.png" width="250" />
</td>
<td style="text-align: center">
<img src="./assets/images/sc4.png" width="250" />
<img src="./images/screenshots/sc4.png" width="250" />
</td>
</tr>
</table>
Expand Down
5 changes: 4 additions & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ if (flutterVersionName == null) {

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
apply plugin: 'com.google.gms.google-services'

Expand Down Expand Up @@ -83,5 +84,7 @@ flutter {
dependencies {
implementation platform("com.google.firebase:firebase-bom:26.5.0")
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "com.google.firebase:firebase-appindexing"
implementation 'com.github.bumptech.glide:glide:4.12.0'
implementation "androidx.cardview:cardview:1.0.0"
kapt 'com.github.bumptech.glide:compiler:4.12.0'
}
40 changes: 26 additions & 14 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,25 @@
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:name="io.flutter.app.FlutterApplication"
android:label="BTTV Stickers"
android:icon="@mipmap/ic_launcher">

<service
android:name=".StickerInputMethod"
android:exported="false"
android:label="BTTV Stickers"
android:permission="android.permission.BIND_INPUT_METHOD">
<meta-data
android:name="android.view.im"
android:resource="@xml/method" />
<intent-filter>
<action android:name="android.view.InputMethod" />
</intent-filter>
</service>

<activity
android:name=".MainActivity"
android:launchMode="singleTop"
Expand Down Expand Up @@ -38,21 +53,18 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="bttvstickers" android:host="emote" />
</intent-filter>
</activity>
<service
android:name=".StickerIndexingService"
android:exported="true"
android:permission="com.google.android.gms.permission.APPINDEXING">
<intent-filter>
<action android:name="com.google.firebase.appindexing.UPDATE_INDEX" />
</intent-filter>
</service>

<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>

<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,6 @@
package com.drakota.bttvstickers

import android.content.Intent
import android.util.Log
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity: FlutterActivity() {
private val CHANNEL = "com.drakota.bttvstickers/sticker_indexing_service"

override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
call, result ->
if (call.method == "generatePack") {
val intent = Intent(baseContext, StickerIndexingService::class.java)
intent.putExtra("emotes", call.arguments as ArrayList<HashMap<String, String>>)
startService(intent)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.drakota.bttvstickers

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.ImageView
import com.bumptech.glide.Glide
import org.json.JSONArray
import org.json.JSONObject


class PackAdapter(var context: Context, var emotes: JSONArray, var commitContent: (emote: JSONObject) -> Unit) : BaseAdapter() {
private val inflator: LayoutInflater = LayoutInflater.from(context)

override fun getCount(): Int {
return emotes.length()
}

override fun getItem(position: Int): JSONObject {
return emotes.get(position) as JSONObject
}

override fun getItemId(position: Int): Long {
return position.toLong()
}

override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val emote = emotes.get(position) as JSONObject
val view = convertView ?: inflator.inflate(R.layout.emote, parent, false)

view.setOnClickListener(View.OnClickListener { _ ->
commitContent(emote)
Utils.performHapticFeedback(context, 15)
return@OnClickListener
})

val imageView = view.findViewById<ImageView>(R.id.EmoteImage)
val url = emote.getString("imageUrl")
Glide.with(context).load(url).into(imageView)
return view
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.drakota.bttvstickers

import android.content.ClipDescription
import android.content.res.Configuration
import android.inputmethodservice.InputMethodService
import android.net.Uri
import android.os.Build
import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.GridView
import androidx.core.content.FileProvider
import androidx.core.view.inputmethod.InputConnectionCompat
import androidx.core.view.inputmethod.InputContentInfoCompat
import com.bumptech.glide.Glide
import org.json.JSONArray
import org.json.JSONObject
import java.io.File


class StickerInputMethod : InputMethodService() {
private val PACK_PATH_PATTERN = "%s/app_flutter/pack.json"

private fun commitImage(emote: JSONObject, contentUri: Uri) {
val mimeType = "image/" + emote.getString("imageType")
val inputContentInfo = InputContentInfoCompat(
contentUri,
ClipDescription(emote.getString("code"), arrayOf(mimeType)),
null
)
val inputConnection = currentInputConnection
val editorInfo = currentInputEditorInfo
var flags = 0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
flags = flags or InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION
}
InputConnectionCompat.commitContent(inputConnection, editorInfo, inputContentInfo, flags, null)
}

private fun commitContent(emote: JSONObject) {
val future = Glide
.with(applicationContext)
.downloadOnly()
.load(emote.getString("imageUrl"))
.submit()

Thread {
val temp = future.get()
val cacheFile = File(applicationContext.externalCacheDir, "cached_sticker")
temp.copyTo(cacheFile, true)

val contentUri = if (Build.VERSION.SDK_INT >= 24)
FileProvider.getUriForFile(
applicationContext,
applicationContext.packageName + ".fileProvider",
cacheFile
)
else
Uri.fromFile(cacheFile)

commitImage(emote, contentUri)
}.start()
}

override fun onStartInputView(info: EditorInfo?, restarting: Boolean) {
setInputView(onCreateInputView())
}

override fun onCreateInputView(): View? {
val root: View = layoutInflater.inflate(R.layout.keyboard, null)
val emoteList: GridView = root.findViewById(R.id.EmoteList)
emoteList.numColumns = if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) 4 else 8
val dataDir = applicationContext.packageManager.getPackageInfo(applicationContext.packageName, 0).applicationInfo.dataDir;
val packFile = File(String.format(PACK_PATH_PATTERN, dataDir))

val emotes = if (packFile.exists()) {
val pack = JSONObject(packFile.readText(Charsets.UTF_8))
pack.getJSONArray("emotes")
} else JSONArray()

emoteList.adapter = PackAdapter(applicationContext, emotes, this::commitContent)
return root
}
}
22 changes: 22 additions & 0 deletions android/app/src/main/kotlin/com/drakota/bttvstickers/Utils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.drakota.bttvstickers

import android.os.Build
import android.os.VibrationEffect
import android.os.Vibrator
import android.content.Context

class Utils {
companion object {
fun performHapticFeedback(context: Context, ms: Long) {
val vibratorService = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vibratorService.let { vs ->
if (Build.VERSION.SDK_INT >= 26) {
vs.vibrate(VibrationEffect.createOneShot(ms, VibrationEffect.DEFAULT_AMPLITUDE))
} else {
@Suppress("DEPRECATION")
vs.vibrate(ms)
}
}
}
}
}
Loading

0 comments on commit 8951a38

Please sign in to comment.