1
0
mirror of https://github.com/AllanWang/Frost-for-Facebook.git synced 2024-11-09 20:42:34 +01:00
* Update play store description

* Finalize description

* Update kotlin and bg2 for custom themes

* Update to Android Studio 3.0 beta 2

* Update test dependencies and add logging to image activity

* Rename throwable to errorRef

* Update searchview and media picker through kau
This commit is contained in:
Allan Wang 2017-08-18 14:40:08 -07:00 committed by GitHub
parent 2eaad9b727
commit 52bfdb66ca
13 changed files with 75 additions and 46 deletions

View File

@ -104,6 +104,7 @@ android {
sourceSets { sourceSets {
main.java.srcDirs += 'src/main/kotlin' main.java.srcDirs += 'src/main/kotlin'
test.java.srcDirs += 'src/test/kotlin' test.java.srcDirs += 'src/test/kotlin'
androidTest.java.srcDirs += 'src/androidTest/kotlin'
} }
packagingOptions { packagingOptions {
@ -119,11 +120,15 @@ repositories {
} }
dependencies { dependencies {
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.3-alpha', { androidTestImplementation("com.android.support.test:runner:${TEST_RUNNER}") {
exclude group: 'com.android.support', module: 'support-annotations' exclude group: 'com.android.support', module: 'support-annotations'
}) }
testImplementation 'junit:junit:4.12' androidTestImplementation "org.jetbrains.kotlin:kotlin-test-junit:${KOTLIN}"
testImplementation "org.robolectric:robolectric:${ROBOELECTRIC}" androidTestImplementation "com.android.support.test:rules:${TEST_RULE}"
testImplementation "org.jetbrains.kotlin:kotlin-test-junit:${KOTLIN}"
testImplementation "junit:junit:${JUNIT}"
implementation "org.jetbrains.kotlin:kotlin-stdlib:${KOTLIN}"
//noinspection GradleDependency //noinspection GradleDependency
implementation "ca.allanwang.kau:adapter:$KAU" implementation "ca.allanwang.kau:adapter:$KAU"
@ -142,8 +147,6 @@ dependencies {
//noinspection GradleDependency //noinspection GradleDependency
implementation "ca.allanwang.kau:core-ui:$KAU" implementation "ca.allanwang.kau:core-ui:$KAU"
testImplementation "org.jetbrains.kotlin:kotlin-test-junit:${KOTLIN}"
debugImplementation "com.squareup.leakcanary:leakcanary-android:${LEAK_CANARY}" debugImplementation "com.squareup.leakcanary:leakcanary-android:${LEAK_CANARY}"
releaseTestImplementation "com.squareup.leakcanary:leakcanary-android-no-op:${LEAK_CANARY}" releaseTestImplementation "com.squareup.leakcanary:leakcanary-android-no-op:${LEAK_CANARY}"
releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:${LEAK_CANARY}" releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:${LEAK_CANARY}"

View File

@ -15,6 +15,7 @@ import android.widget.ProgressBar
import android.widget.TextView import android.widget.TextView
import ca.allanwang.kau.email.sendEmail import ca.allanwang.kau.email.sendEmail
import ca.allanwang.kau.internal.KauBaseActivity import ca.allanwang.kau.internal.KauBaseActivity
import ca.allanwang.kau.mediapicker.scanMedia
import ca.allanwang.kau.permissions.PERMISSION_WRITE_EXTERNAL_STORAGE import ca.allanwang.kau.permissions.PERMISSION_WRITE_EXTERNAL_STORAGE
import ca.allanwang.kau.permissions.kauRequestPermissions import ca.allanwang.kau.permissions.kauRequestPermissions
import ca.allanwang.kau.utils.* import ca.allanwang.kau.utils.*
@ -47,6 +48,7 @@ class ImageActivity : KauBaseActivity() {
val photo: SubsamplingScaleImageView by bindView(R.id.image_photo) val photo: SubsamplingScaleImageView by bindView(R.id.image_photo)
val caption: TextView? by bindOptionalView(R.id.image_text) val caption: TextView? by bindOptionalView(R.id.image_text)
val fab: FloatingActionButton by bindView(R.id.image_fab) val fab: FloatingActionButton by bindView(R.id.image_fab)
var errorRef: Throwable? = null
/** /**
* Reference to the temporary file path * Reference to the temporary file path
@ -85,17 +87,16 @@ class ImageActivity : KauBaseActivity() {
caption?.text = text caption?.text = text
progress.tint(Prefs.accentColor) progress.tint(Prefs.accentColor)
panel?.addPanelSlideListener(object : SlidingUpPanelLayout.SimplePanelSlideListener() { panel?.addPanelSlideListener(object : SlidingUpPanelLayout.SimplePanelSlideListener() {
override fun onPanelSlide(panel: View, slideOffset: Float) { override fun onPanelSlide(panel: View, slideOffset: Float) {
if (slideOffset == 0f && !fab.isShown) fab.show() if (slideOffset == 0f && !fab.isShown) fab.show()
else if (slideOffset != 0f && fab.isShown) fab.hide() else if (slideOffset != 0f && fab.isShown) fab.hide()
caption?.alpha = slideOffset / 2 + 0.5f caption?.alpha = slideOffset / 2 + 0.5f
} }
}) })
fab.setOnClickListener { fabAction.onClick(this) } fab.setOnClickListener { fabAction.onClick(this) }
photo.setOnImageEventListener(object : SubsamplingScaleImageView.DefaultOnImageEventListener() { photo.setOnImageEventListener(object : SubsamplingScaleImageView.DefaultOnImageEventListener() {
override fun onImageLoadError(e: Exception?) { override fun onImageLoadError(e: Exception?) {
errorRef = e
e.logFrostAnswers("Image load error") e.logFrostAnswers("Image load error")
imageCallback(null, false) imageCallback(null, false)
} }
@ -145,7 +146,8 @@ class ImageActivity : KauBaseActivity() {
var photoFile: File? = null var photoFile: File? = null
try { try {
photoFile = createPrivateMediaFile(".png") photoFile = createPrivateMediaFile(".png")
} catch (ignored: IOException) { } catch (e: IOException) {
errorRef = e
} finally { } finally {
if (photoFile == null) { if (photoFile == null) {
callback(null) callback(null)
@ -173,8 +175,9 @@ class ImageActivity : KauBaseActivity() {
var success = true var success = true
try { try {
File(tempFilePath).copyTo(destination, true) File(tempFilePath).copyTo(destination, true)
scanFile(destination) scanMedia(destination)
} catch (e: Exception) { } catch (e: Exception) {
errorRef = e
success = false success = false
} finally { } finally {
L.d("Download image async finished: $success") L.d("Download image async finished: $success")
@ -189,17 +192,6 @@ class ImageActivity : KauBaseActivity() {
} }
} }
/**
* See <a href="https://developer.android.com/training/camera/photobasics.html#TaskGallery">Docs</a>
*/
internal fun scanFile(file: File) {
if (!file.exists()) return
val mediaScanIntent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
val contentUri = Uri.fromFile(file)
mediaScanIntent.data = contentUri
this.sendBroadcast(mediaScanIntent)
}
internal fun deleteTempFile() { internal fun deleteTempFile() {
if (tempFilePath != null) { if (tempFilePath != null) {
File(tempFilePath!!).delete() File(tempFilePath!!).delete()
@ -221,8 +213,11 @@ internal enum class FabStates(val iicon: IIcon, val iconColor: Int = Prefs.iconC
content(R.string.bad_image_overlay) content(R.string.bad_image_overlay)
positiveText(R.string.kau_yes) positiveText(R.string.kau_yes)
onPositive { _, _ -> onPositive { _, _ ->
if (activity.errorRef != null)
L.e(activity.errorRef, "ImageActivity error report")
activity.sendEmail(R.string.dev_email, R.string.debug_image_link_subject) { activity.sendEmail(R.string.dev_email, R.string.debug_image_link_subject) {
addItem("Url", activity.imageUrl) addItem("Url", activity.imageUrl)
addItem("Message", activity.errorRef?.message ?: "Null")
} }
} }
negativeText(R.string.kau_no) negativeText(R.string.kau_no)
@ -248,6 +243,7 @@ internal enum class FabStates(val iicon: IIcon, val iconColor: Int = Prefs.iconC
} }
activity.startActivity(intent) activity.startActivity(intent)
} catch (e: Exception) { } catch (e: Exception) {
activity.errorRef = e
e.logFrostAnswers("Image share failed") e.logFrostAnswers("Image share failed")
activity.snackbar(R.string.image_share_failed) activity.snackbar(R.string.image_share_failed)
} }

View File

@ -1,6 +1,5 @@
package com.pitchedapps.frost.activities package com.pitchedapps.frost.activities
import android.content.Intent
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler

View File

@ -368,6 +368,7 @@ class MainActivity : BaseActivity(), SearchWebView.SearchContract,
if (firstLoadFinished && hiddenSearchView == null) hiddenSearchView = SearchWebView(this, this) if (firstLoadFinished && hiddenSearchView == null) hiddenSearchView = SearchWebView(this, this)
if (searchView == null) searchView = bindSearchView(menu, R.id.action_search, Prefs.iconColor) { if (searchView == null) searchView = bindSearchView(menu, R.id.action_search, Prefs.iconColor) {
textCallback = { query, _ -> runOnUiThread { hiddenSearchView?.query(query) } } textCallback = { query, _ -> runOnUiThread { hiddenSearchView?.query(query) } }
searchCallback = { query, _ -> launchWebOverlay("${FbItem.SEARCH.url}/?q=$query"); true }
foregroundColor = Prefs.textColor foregroundColor = Prefs.textColor
backgroundColor = Prefs.bgColor.withMinAlpha(200) backgroundColor = Prefs.bgColor.withMinAlpha(200)
openListener = { hiddenSearchView?.pauseLoad = false } openListener = { hiddenSearchView?.pauseLoad = false }

View File

@ -1,10 +1,26 @@
package com.pitchedapps.frost.activities package com.pitchedapps.frost.activities
import ca.allanwang.kau.mediapicker.MediaPickerActivityOverlayBase import android.content.Context
import ca.allanwang.kau.mediapicker.MediaType import android.net.Uri
import android.support.v4.content.FileProvider
import ca.allanwang.kau.mediapicker.*
import com.pitchedapps.frost.BuildConfig
import com.pitchedapps.frost.utils.Prefs
import java.io.File
/** /**
* Created by Allan Wang on 2017-07-23. * Created by Allan Wang on 2017-07-23.
*/ */
class ImagePickerActivity : MediaPickerActivityOverlayBase(MediaType.IMAGE) private fun actions() = listOf(object : MediaActionCamera(Prefs.accentColor) {
class VideoPickerActivity : MediaPickerActivityOverlayBase(MediaType.VIDEO)
override fun createFile(context: Context): File
= createMediaFile("Frost", ".jpg")
override fun createUri(context: Context, file: File): Uri
= FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", file)
}, MediaActionGallery(color = Prefs.accentColor))
class ImagePickerActivity : MediaPickerActivityOverlayBase(MediaType.IMAGE, actions())
class VideoPickerActivity : MediaPickerActivityOverlayBase(MediaType.VIDEO, actions())

View File

@ -25,13 +25,10 @@ enum class CssAssets(val folder: String = "themes") : InjectorContract {
try { try {
var content = webView.context.assets.open("css/$folder/$file").bufferedReader().use { it.readText() } var content = webView.context.assets.open("css/$folder/$file").bufferedReader().use { it.readText() }
if (this == CUSTOM) { if (this == CUSTOM) {
var bbt = Prefs.bgColor
val bt: String val bt: String
if (Color.alpha(bbt) == 255) { if (Color.alpha(Prefs.bgColor) == 255) {
bbt = bbt.adjustAlpha(0.2f).colorToForeground(0.35f)
bt = Prefs.bgColor.toRgbaString() bt = Prefs.bgColor.toRgbaString()
} else { } else {
bbt = bbt.adjustAlpha(0.05f).colorToForeground(0.5f)
bt = "transparent" bt = "transparent"
} }
content = content content = content
@ -39,7 +36,7 @@ enum class CssAssets(val folder: String = "themes") : InjectorContract {
.replace("\$TT\$", Prefs.textColor.colorToBackground(0.05f).toRgbaString()) .replace("\$TT\$", Prefs.textColor.colorToBackground(0.05f).toRgbaString())
.replace("\$B\$", Prefs.bgColor.toRgbaString()) .replace("\$B\$", Prefs.bgColor.toRgbaString())
.replace("\$BT\$", bt) .replace("\$BT\$", bt)
.replace("\$BBT\$", bbt.toRgbaString()) .replace("\$BBT\$", Prefs.bgColor.withAlpha(51).colorToForeground(0.35f).toRgbaString())
.replace("\$O\$", Prefs.bgColor.withAlpha(255).toRgbaString()) .replace("\$O\$", Prefs.bgColor.withAlpha(255).toRgbaString())
.replace("\$OO\$", Prefs.bgColor.colorToForeground(0.35f).withAlpha(255).toRgbaString()) .replace("\$OO\$", Prefs.bgColor.colorToForeground(0.35f).withAlpha(255).toRgbaString())
.replace("\$D\$", Prefs.textColor.adjustAlpha(0.3f).toRgbaString()) .replace("\$D\$", Prefs.textColor.adjustAlpha(0.3f).toRgbaString())

View File

@ -13,6 +13,8 @@ import android.support.v7.widget.Toolbar
import android.view.View import android.view.View
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.TextView import android.widget.TextView
import ca.allanwang.kau.mediapicker.createMediaFile
import ca.allanwang.kau.mediapicker.createPrivateMediaFile
import ca.allanwang.kau.utils.* import ca.allanwang.kau.utils.*
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import com.bumptech.glide.RequestBuilder import com.bumptech.glide.RequestBuilder

View File

@ -8,7 +8,6 @@ import android.webkit.*
import ca.allanwang.kau.utils.fadeIn import ca.allanwang.kau.utils.fadeIn
import ca.allanwang.kau.utils.isVisible import ca.allanwang.kau.utils.isVisible
import com.pitchedapps.frost.dbflow.CookieModel import com.pitchedapps.frost.dbflow.CookieModel
import com.pitchedapps.frost.facebook.FACEBOOK_COM
import com.pitchedapps.frost.facebook.FB_URL_BASE import com.pitchedapps.frost.facebook.FB_URL_BASE
import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.facebook.FbCookie
import com.pitchedapps.frost.injectors.CssHider import com.pitchedapps.frost.injectors.CssHider

View File

@ -1,12 +1,18 @@
<b>Welcome to Frost for Facebook!</b>
Frost is a fully themable, fully functional alternative to the official Facebook app. Frost is a fully themable, fully functional alternative to the official Facebook app.
While being a web wrapper, Frost contains many unique and native features such as: While being a web wrapper, Frost contains many unique and native features such as:
• True multi user interactions - More than just an option in a settings menu, Frost's account switcher is right in the drawer. You are one tap away from switching accounts, and everything refreshes on the switch so that you can view other accounts instantaneously. Furthermore, the notification service will fetch notifications from all accounts, and will let you know which account has the new notification. • <b>True multi user interactions</b> - More than just an option in a settings menu, Frost's account switcher is right in the drawer. You are one tap away from switching accounts, and everything refreshes on the switch so that you can view other accounts instantaneously. Furthermore, the notification service will fetch notifications from all accounts, and will let you know which account has the new notification.
• Better multitasking - Frost contains an overlaying web browser that can be drawn on top of your foreground task. Open links and notifications with a full screen view, then swipe away to get back to your previous task. • <b>Better multitasking</b> - Frost contains an overlaying web browser that can be drawn on top of your foreground task. Open links and notifications with a full screen view, then swipe away to get back to your previous task.
• Contextual awareness - Frost integrates additional features via long presses. Need to copy a block of text or share a link? Long press the text. Need to zoom into an image or download it? Long press the image! • <b>Contextual awareness</b> - Frost integrates additional features via long presses. Need to copy a block of text or share a link? Long press the text. Need to zoom into an image or download it? Long press the image!
• Material Design - Built for lollipop and up, Frost focuses strongly on a good UI, and embraces material transitions and dimensions. • <b>Material Design</b> - Built for lollipop and up, Frost focuses strongly on a beautiful and functional UI, and embraces material transitions and dimensions.
• Complete theme engine - Frost contains very comprehensive themes that customize all components of the app. Frost is also the only app to support transparent themes. • <b>Complete theme engine</b> - Frost contains very comprehensive themes that customize all components of the app. Frost is also the only app to support transparent themes.
• Fully opened - Nothing speaks for privacy more than being open sourced. Frost is proud to be one of those apps, and can be found on github (Link in the app's about section) • <b>Fully opened</b> - Nothing speaks for privacy more than being open sourced. Frost is proud to be one of those apps, and can be found on github (Link in the app's about section)
• <b>Fixes the little things</b> - Frost is community driven, and many tweaks are added to address minor inconveniences and give a full native experience, despite being a web app. To list a few:
&emsp;&emsp; • Focusing on a text input will prevent refreshing, so you don't accidentally swipe and lose your progress.
&emsp;&emsp; • Horizontal swipe can be enabled along side the viewpager swipe with a simple long press
&emsp;&emsp; • Automatic bug reports are sent when a crash is detected, so even if you don't contact the devs, you are helping contribute by using the app.
Mandatory permissions used and why: Mandatory permissions used and why:
@ -16,13 +22,14 @@ Mandatory permissions used and why:
• Billing - For purchasing pro and unlocking all of Frost's features • Billing - For purchasing pro and unlocking all of Frost's features
Optional permissions used and why: Optional permissions used and why:
(these are only requested when they have to be, and are disabled until then) <i>(these are only requested when they have to be, and are disabled until then)</i>
• Read/write external storage - Needed to upload photos in a new status and save photos when prompted • Read/write external storage - Needed to upload photos in a new status and save photos when prompted
• Fine/coarse location - Needed for the check in option if users wish to search for their location • Fine/coarse location - Needed for the check in option if users wish to search for their location
• That's it! No privacy intrusion and no extra demands. • That's it! No privacy intrusion and no extra demands.
Permissions NOT used and why: Permissions <i>NOT</i> used and why:
• Wakelock - Frost takes advantage of Android's Job Scheduler, and lets the framework decide when to run background services. Frost therefore doesn't need to constantly run in the background, nor does it force your phone to stay awake. • Wakelock - Frost takes advantage of Android's Job Scheduler, and lets the framework decide when to run background services. Frost therefore doesn't need to constantly run in the background, nor does it force your phone to stay awake.
• Retrieve running apps - Frost has no need to access external apps or see what else is running • Retrieve running apps - Frost has no need to access external apps or see what else is running

View File

@ -11,14 +11,16 @@
<!--<version title="Beta Updates" />--> <!--<version title="Beta Updates" />-->
<version title="Beta Updates"/> <version title="Beta Updates"/>
<item text="Create more robust IM notification fetcher with a timeout" /> <item text="Update secondary background for transparent themes to be more visible." />
<item text="" />
<version title="v1.4.5"/>
<item text="Create more robust IM notification fetcher with a timeout" />
<item text="Add hidden debugging options for certain views" /> <item text="Add hidden debugging options for certain views" />
<item text="Separate IM and general notification groups" /> <item text="Separate IM and general notification groups" />
<item text="Add click actions to group notifications. They will launch the message page or the notification page respectively" /> <item text="Add click actions to group notifications. They will launch the message page or the notification page respectively" />
<item text="Add behaviour setting to force message threads to scroll to the bottom after loading." /> <item text="Add behaviour setting to force message threads to scroll to the bottom after loading." />
<item text="Add faq for disabling video auto play" /> <item text="Add faq for disabling video auto play" />
<item text="" />
<item text="" />
<version title="v1.4.2"/> <version title="v1.4.2"/>
<item text="Experimental: Add notifications for messages; report to me if this drains your battery" /> <item text="Experimental: Add notifications for messages; report to me if this drains your battery" />

View File

@ -7,7 +7,7 @@ buildscript {
maven { url 'https://maven.fabric.io/public' } maven { url 'https://maven.fabric.io/public' }
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.0.0-alpha9' classpath 'com.android.tools.build:gradle:3.0.0-beta2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${KOTLIN}" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${KOTLIN}"
classpath 'io.fabric.tools:gradle:1.+' classpath 'io.fabric.tools:gradle:1.+'
classpath 'com.github.triplet.gradle:play-publisher:1.2.0' classpath 'com.github.triplet.gradle:play-publisher:1.2.0'

View File

@ -1,6 +1,9 @@
# Changelog # Changelog
## Beta Updates ## Beta Updates
* Update secondary background for transparent themes to be more visible.
## v1.4.5
* Create more robust IM notification fetcher with a timeout * Create more robust IM notification fetcher with a timeout
* Add hidden debugging options for certain views * Add hidden debugging options for certain views
* Separate IM and general notification groups * Separate IM and general notification groups

View File

@ -17,8 +17,8 @@ MIN_SDK=21
TARGET_SDK=26 TARGET_SDK=26
BUILD_TOOLS=26.0.1 BUILD_TOOLS=26.0.1
KAU=4d3d570 KAU=caab9d5
KOTLIN=1.1.3-2 KOTLIN=1.1.4
CRASHLYTICS=2.6.8 CRASHLYTICS=2.6.8
DBFLOW=4.0.5 DBFLOW=4.0.5
@ -39,4 +39,8 @@ RX_NETWORK=0.11.0
SCALE_IMAGE_VIEW=3.6.0 SCALE_IMAGE_VIEW=3.6.0
SLIDING_PANEL=3.3.1 SLIDING_PANEL=3.3.1
JUNIT=4.12
TEST_RULE=0.5
TEST_RUNNER=1.0.0
android.enableAapt2=false android.enableAapt2=false