mirror of
https://github.com/AllanWang/Frost-for-Facebook.git
synced 2024-09-19 23:21:34 +02:00
Parse header badges
This commit is contained in:
parent
0720413ee8
commit
382433780c
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,3 +10,4 @@
|
||||
/app/src/main/res/values/strings_facebook.xml
|
||||
/app/src/main/kotlin/com/pitchedapps/frost/facebook/Private.kt
|
||||
*.min.css
|
||||
.sass-cache/
|
@ -96,6 +96,8 @@ dependencies {
|
||||
|
||||
testCompile "org.robolectric:robolectric:${ROBOELECTRIC}"
|
||||
|
||||
compile "org.greenrobot:eventbus:${EVENTBUS}"
|
||||
|
||||
//Icons
|
||||
compile "com.mikepenz:google-material-typeface:${IICON_GOOGLE}.original@aar"
|
||||
compile "com.mikepenz:material-design-iconic-typeface:${IICON_MATERIAL}@aar"
|
||||
|
@ -10,8 +10,6 @@
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
|
||||
<application
|
||||
android:name=".FrostApp"
|
||||
@ -111,15 +109,13 @@
|
||||
<service
|
||||
android:name=".services.NotificationService"
|
||||
android:enabled="true"
|
||||
android:label="@string/frost_notifications" />
|
||||
android:label="@string/frost_notifications"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
<receiver
|
||||
android:name=".services.NotificationReceiver"
|
||||
android:enabled="true"
|
||||
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
|
||||
android:name=".services.UpdateReceiver"
|
||||
android:enabled="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.PACKAGE_REPLACED" />
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
<action android:name="com.pitchedapps.frost.NOTIFICATIONS" />
|
||||
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<meta-data
|
||||
|
3
app/src/main/assets/js/header_badges.js
Normal file
3
app/src/main/assets/js/header_badges.js
Normal file
@ -0,0 +1,3 @@
|
||||
//bases the header contents if it exists
|
||||
var header = document.getElementById('mJewelNav');
|
||||
if (header !== null) Frost.handleHeader(header.outerHTML);
|
3
app/src/main/assets/js/header_badges.min.js
vendored
Normal file
3
app/src/main/assets/js/header_badges.min.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
var header=document.getElementById("mJewelNav")
|
||||
|
||||
;null!==header&&Frost.handleHeader(header.outerHTML);
|
@ -30,8 +30,12 @@ import com.pitchedapps.frost.facebook.FbTab
|
||||
import com.pitchedapps.frost.facebook.PROFILE_PICTURE_URL
|
||||
import com.pitchedapps.frost.fragments.WebFragment
|
||||
import com.pitchedapps.frost.utils.*
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import io.reactivex.subjects.PublishSubject
|
||||
import org.jetbrains.anko.childrenSequence
|
||||
import org.jsoup.Jsoup
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class MainActivity : BaseActivity() {
|
||||
|
||||
@ -45,6 +49,7 @@ class MainActivity : BaseActivity() {
|
||||
lateinit var drawerHeader: AccountHeader
|
||||
var webFragmentObservable = PublishSubject.create<Int>()!!
|
||||
var lastPosition = -1
|
||||
val headerBadgeObservable = PublishSubject.create<String>()
|
||||
|
||||
companion object {
|
||||
const val FRAGMENT_REFRESH = 99
|
||||
@ -97,6 +102,22 @@ class MainActivity : BaseActivity() {
|
||||
currentFragment.web.scrollOrRefresh()
|
||||
}
|
||||
})
|
||||
headerBadgeObservable.throttleFirst(15, TimeUnit.SECONDS).subscribeOn(Schedulers.newThread())
|
||||
.map { Jsoup.parse(it) }
|
||||
.filter { it.select("[data-sigil=\"count\"]").size >= 0 } //ensure headers exist
|
||||
.map {
|
||||
val feed = it.select("[data-sigil*=\"feed\"] [data-sigil=\"count\"]")
|
||||
val requests = it.select("[data-sigil*=\"requests\"] [data-sigil=\"count\"]")
|
||||
val messages = it.select("[data-sigil*=\"messages\"] [data-sigil=\"count\"]")
|
||||
val notifications = it.select("[data-sigil*=\"notifications\"] [data-sigil=\"count\"]")
|
||||
return@map arrayOf(feed, requests, messages, notifications).map { it?.getOrNull(0)?.ownText() }
|
||||
}
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
(feed, requests, messages, notifications) ->
|
||||
L.d("Header subscription $feed $requests $messages $notifications")
|
||||
L.d("contained nulls ${feed == null}")
|
||||
}
|
||||
adapter.pages.forEach { tabs.addTab(tabs.newTab().setIcon(it.icon.toDrawable(this, sizeDp = 20, color = Prefs.iconColor))) }
|
||||
}
|
||||
|
||||
|
@ -6,16 +6,18 @@ import ca.allanwang.kau.kpref.KPrefAdapterBuilder
|
||||
import ca.allanwang.kau.utils.*
|
||||
import ca.allanwang.kau.views.RippleCanvas
|
||||
import com.pitchedapps.frost.utils.*
|
||||
import org.jetbrains.anko.toast
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-06-06.
|
||||
*/
|
||||
class SettingsActivity : KPrefActivity() {
|
||||
|
||||
override fun onCreateKPrefs(savedInstanceState: android.os.Bundle?): KPrefAdapterBuilder.() -> Unit = {
|
||||
textColor = { Prefs.textColor }
|
||||
accentColor = { Prefs.textColor }
|
||||
header(R.string.settings)
|
||||
text<Int>(R.string.theme, { Prefs.theme }, { Prefs.theme = it }) {
|
||||
text(R.string.theme, { Prefs.theme }, { Prefs.theme = it }) {
|
||||
onClick = {
|
||||
_, _, item ->
|
||||
this@SettingsActivity.materialDialogThemed {
|
||||
@ -65,16 +67,40 @@ class SettingsActivity : KPrefActivity() {
|
||||
allowCustom = true
|
||||
}
|
||||
|
||||
colorPicker(R.string.icon_color, { Prefs.customIconColor }, { Prefs.customIconColor = it; toolbar.setTitleTextColor(it) }) {
|
||||
enabler = { Prefs.isCustomTheme }
|
||||
onDisabledClick = { itemView, _, _ -> itemView.snackbar(R.string.requires_custom_theme); true }
|
||||
allowCustomAlpha = false
|
||||
allowCustom = true
|
||||
fun Long.timeToText(): String =
|
||||
if (this == -1L) string(R.string.none)
|
||||
else if (this == 60L) string(R.string.one_hour)
|
||||
else if (this == 1440L) string(R.string.one_day)
|
||||
else if (this % 1440L == 0L) String.format(string(R.string.x_days), this / 1440L)
|
||||
else if (this % 60L == 0L) String.format(string(R.string.x_hours), this / 60L)
|
||||
else String.format(string(R.string.x_minutes), this)
|
||||
|
||||
text(R.string.notifications, { Prefs.notificationFreq }, { Prefs.notificationFreq = it; reloadByTitle(R.string.notifications) }) {
|
||||
val options = longArrayOf(-1, 15, 30, 60, 120, 180, 300, 1440, 2880)
|
||||
val texts = options.map { it.timeToText() }
|
||||
onClick = {
|
||||
_, _, item ->
|
||||
this@SettingsActivity.materialDialogThemed {
|
||||
title(R.string.notifications)
|
||||
items(texts)
|
||||
itemsCallbackSingleChoice(options.indexOf(item.pref), {
|
||||
_, _, which, text ->
|
||||
item.pref = options[which]
|
||||
this@SettingsActivity.scheduleNotifications(item.pref)
|
||||
this@SettingsActivity.toast(text)
|
||||
true
|
||||
})
|
||||
}
|
||||
true
|
||||
}
|
||||
textGetter = { it.timeToText() }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setFrostTheme()
|
||||
themeExterior(false)
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,9 @@ fun loadFbCookiesAsync(callback: (cookies: List<CookieModel>) -> Unit) {
|
||||
(select from CookieModel::class).orderBy(CookieModel_Table.name, true).async().queryListResultCallback { _, tResult -> callback.invoke(tResult) }.execute()
|
||||
}
|
||||
|
||||
fun loadFbCookiesSync(): List<CookieModel> = (select from CookieModel::class).orderBy(CookieModel_Table.name, true).queryList()
|
||||
|
||||
|
||||
fun saveFbCookie(cookie: CookieModel, callback: (() -> Unit)? = null) {
|
||||
cookie.async save {
|
||||
L.d("Fb cookie $cookie saved")
|
||||
|
@ -10,7 +10,7 @@ import com.pitchedapps.frost.utils.L
|
||||
* //TODO add folder mapping using Prefs
|
||||
*/
|
||||
enum class JsAssets : InjectorContract {
|
||||
MENU, MENU_CLICK, CLICK_INTERCEPTOR
|
||||
MENU, MENU_CLICK, CLICK_INTERCEPTOR, HEADER_BADGES
|
||||
;
|
||||
|
||||
var file = "${name.toLowerCase()}.min.js"
|
||||
|
@ -1,20 +0,0 @@
|
||||
package com.pitchedapps.frost.services
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-05-31.
|
||||
*/
|
||||
class NotificationReceiver : BroadcastReceiver() {
|
||||
|
||||
companion object {
|
||||
const val ACTION = "com.pitchedapps.frost.NOTIFICATIONS"
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if (intent.action != ACTION) return
|
||||
}
|
||||
|
||||
}
|
@ -1,14 +1,18 @@
|
||||
package com.pitchedapps.frost.services
|
||||
|
||||
import android.app.IntentService
|
||||
import android.app.Notification
|
||||
import android.app.PendingIntent
|
||||
import android.app.job.JobParameters
|
||||
import android.app.job.JobService
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Looper
|
||||
import android.support.v4.app.ActivityOptionsCompat
|
||||
import android.support.v4.app.NotificationCompat
|
||||
import android.support.v4.app.NotificationManagerCompat
|
||||
import ca.allanwang.kau.utils.checkThread
|
||||
import ca.allanwang.kau.utils.string
|
||||
import com.pitchedapps.frost.BuildConfig
|
||||
import com.pitchedapps.frost.R
|
||||
import com.pitchedapps.frost.WebOverlayActivity
|
||||
import com.pitchedapps.frost.dbflow.*
|
||||
@ -17,13 +21,53 @@ import com.pitchedapps.frost.facebook.FB_URL_BASE
|
||||
import com.pitchedapps.frost.facebook.FbTab
|
||||
import com.pitchedapps.frost.utils.ARG_URL
|
||||
import com.pitchedapps.frost.utils.L
|
||||
import org.jetbrains.anko.doAsync
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Element
|
||||
import java.util.concurrent.Future
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-06-14.
|
||||
*/
|
||||
class NotificationService : IntentService(NotificationService::class.java.simpleName) {
|
||||
class NotificationService : JobService() {
|
||||
|
||||
var future: Future<Unit>? = null
|
||||
|
||||
override fun onStopJob(params: JobParameters?): Boolean {
|
||||
future?.cancel(true)
|
||||
future = null
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onStartJob(params: JobParameters?): Boolean {
|
||||
future = doAsync {
|
||||
loadFbCookiesSync().forEach {
|
||||
data ->
|
||||
L.i("Handling notifications for ${data.id}")
|
||||
L.v("Using data $data")
|
||||
val doc = Jsoup.connect(FbTab.NOTIFICATIONS.url).cookie(FACEBOOK_COM, data.cookie).get()
|
||||
val unreadNotifications = doc.getElementById("notifications_list").getElementsByClass("aclb")
|
||||
var notifCount = 0
|
||||
var latestEpoch = lastNotificationTime(data.id)
|
||||
L.v("Latest Epoch $latestEpoch")
|
||||
unreadNotifications.forEach unread@ {
|
||||
elem ->
|
||||
val notif = parseNotification(data, elem)
|
||||
if (notif != null) {
|
||||
if (notif.timestamp <= latestEpoch) return@unread
|
||||
notif.createNotification(this@NotificationService)
|
||||
latestEpoch = notif.timestamp
|
||||
notifCount++
|
||||
}
|
||||
}
|
||||
if (notifCount > 0) saveNotificationTime(NotificationModel(data.id, latestEpoch))
|
||||
summaryNotification(data.id, notifCount)
|
||||
}
|
||||
L.d("Finished notifications")
|
||||
jobFinished(params, false)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ARG_ID = "arg_id"
|
||||
@ -31,31 +75,6 @@ class NotificationService : IntentService(NotificationService::class.java.simple
|
||||
val notifIdMatcher: Regex by lazy { Regex("notif_id\":([0-9]*),") }
|
||||
}
|
||||
|
||||
override fun onHandleIntent(intent: Intent) {
|
||||
val id = intent.getLongExtra(ARG_ID, -1L)
|
||||
L.i("Handling notifications for $id")
|
||||
if (id == -1L) return
|
||||
val data = loadFbCookie(id) ?: return
|
||||
L.v("Using data $data")
|
||||
val doc = Jsoup.connect(FbTab.NOTIFICATIONS.url).cookie(FACEBOOK_COM, data.cookie).get()
|
||||
val unreadNotifications = doc.getElementById("notifications_list").getElementsByClass("aclb")
|
||||
var notifCount = 0
|
||||
var latestEpoch = lastNotificationTime(data.id)
|
||||
L.v("Latest Epoch $latestEpoch")
|
||||
unreadNotifications.forEach {
|
||||
elem ->
|
||||
val notif = parseNotification(data, elem)
|
||||
if (notif != null) {
|
||||
if (notif.timestamp <= latestEpoch) return@forEach
|
||||
notif.createNotification(this)
|
||||
latestEpoch = notif.timestamp
|
||||
notifCount++
|
||||
}
|
||||
}
|
||||
if (notifCount > 0) saveNotificationTime(NotificationModel(data.id, latestEpoch))
|
||||
summaryNotification(data.id, notifCount)
|
||||
}
|
||||
|
||||
fun parseNotification(data: CookieModel, element: Element): NotificationContent? {
|
||||
val a = element.getElementsByTag("a").first() ?: return null
|
||||
val dataStore = a.attr("data-store")
|
||||
@ -71,6 +90,18 @@ class NotificationService : IntentService(NotificationService::class.java.simple
|
||||
return NotificationContent(data, notifId.toInt(), a.attr("href"), text, epoch)
|
||||
}
|
||||
|
||||
private fun Context.debugNotification(text: String) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
val notifBuilder = NotificationCompat.Builder(this)
|
||||
.setSmallIcon(R.drawable.frost_f_24)
|
||||
.setContentTitle(string(R.string.app_name))
|
||||
.setContentText(text)
|
||||
.setAutoCancel(true)
|
||||
|
||||
NotificationManagerCompat.from(this).notify(999, notifBuilder.build())
|
||||
}
|
||||
}
|
||||
|
||||
data class NotificationContent(val data: CookieModel, val notifId: Int, val href: String, val text: String, val timestamp: Long) {
|
||||
fun createNotification(context: Context) {
|
||||
val intent = Intent(context, WebOverlayActivity::class.java)
|
||||
|
@ -0,0 +1,20 @@
|
||||
package com.pitchedapps.frost.services
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import com.pitchedapps.frost.utils.L
|
||||
import com.pitchedapps.frost.utils.Prefs
|
||||
import com.pitchedapps.frost.utils.scheduleNotifications
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-05-31.
|
||||
*/
|
||||
class UpdateReceiver : BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
L.d("Frost has updated")
|
||||
context.scheduleNotifications(Prefs.notificationFreq) //Update notifications
|
||||
}
|
||||
|
||||
}
|
@ -31,6 +31,8 @@ object Prefs : KPref() {
|
||||
|
||||
var exitConfirmation: Boolean by kpref("exit_confirmation", true)
|
||||
|
||||
var notificationFreq: Long by kpref("notification_freq", -1L)
|
||||
|
||||
private val loader = lazyResettable { Theme.values[Prefs.theme] }
|
||||
|
||||
private val t: Theme by loader
|
||||
|
@ -1,11 +1,13 @@
|
||||
package com.pitchedapps.frost.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.job.JobInfo
|
||||
import android.app.job.JobScheduler
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.support.v4.app.ActivityOptionsCompat
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v7.widget.Toolbar
|
||||
import android.view.View
|
||||
@ -18,6 +20,7 @@ import com.pitchedapps.frost.WebOverlayActivity
|
||||
import com.pitchedapps.frost.dbflow.CookieModel
|
||||
import com.pitchedapps.frost.facebook.FB_URL_BASE
|
||||
import com.pitchedapps.frost.facebook.FbTab
|
||||
import com.pitchedapps.frost.services.NotificationService
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-06-03.
|
||||
@ -99,4 +102,27 @@ fun Activity.setFrostColors(toolbar: Toolbar? = null, themeWindow: Boolean = tru
|
||||
texts.forEach { it.setTextColor(Prefs.textColor) }
|
||||
headers.forEach { it.setBackgroundColor(darkAccent) }
|
||||
backgrounds.forEach { it.setBackgroundColor(Prefs.bgColor) }
|
||||
}
|
||||
|
||||
|
||||
const val NOTIFICATION_JOB = 7
|
||||
/**
|
||||
* [interval] is # of min, which must be at least 15
|
||||
* returns false if an error occurs; true otherwise
|
||||
*/
|
||||
fun Context.scheduleNotifications(minutes: Long): Boolean {
|
||||
val scheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
|
||||
scheduler.cancel(NOTIFICATION_JOB)
|
||||
if (minutes < 0L) return true
|
||||
val serviceComponent = ComponentName(this, NotificationService::class.java)
|
||||
val builder = JobInfo.Builder(NOTIFICATION_JOB, serviceComponent)
|
||||
.setPeriodic(minutes * 60000)
|
||||
.setPersisted(true)
|
||||
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) //TODO add options
|
||||
val result = scheduler.schedule(builder.build())
|
||||
if (result <= 0) {
|
||||
L.e("Notification scheduler failed")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
@ -10,12 +10,16 @@ import com.pitchedapps.frost.utils.L
|
||||
import com.pitchedapps.frost.utils.cookies
|
||||
import com.pitchedapps.frost.utils.launchNewTask
|
||||
import com.pitchedapps.frost.utils.launchWebOverlay
|
||||
import io.reactivex.subjects.Subject
|
||||
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-06-01.
|
||||
*/
|
||||
class FrostJSI(val context: Context, val webView: FrostWebViewCore) {
|
||||
|
||||
val headerObservable: Subject<String>? = (context as? MainActivity)?.headerBadgeObservable
|
||||
|
||||
val cookies: ArrayList<CookieModel>
|
||||
get() = (context as? MainActivity)?.cookies() ?: arrayListOf()
|
||||
|
||||
@ -51,4 +55,9 @@ class FrostJSI(val context: Context, val webView: FrostWebViewCore) {
|
||||
webView.post { webView.frostWebClient!!.handleHtml(html) }
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun handleHeader(html: String) {
|
||||
headerObservable?.onNext(html)
|
||||
}
|
||||
|
||||
}
|
@ -3,7 +3,10 @@ package com.pitchedapps.frost.web
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.view.KeyEvent
|
||||
import android.webkit.*
|
||||
import android.webkit.WebResourceRequest
|
||||
import android.webkit.WebResourceResponse
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import com.pitchedapps.frost.LoginActivity
|
||||
import com.pitchedapps.frost.MainActivity
|
||||
import com.pitchedapps.frost.SelectorActivity
|
||||
@ -50,7 +53,7 @@ open class FrostWebViewClient(val webCore: FrostWebViewCore) : WebViewClient() {
|
||||
refreshObservable.onNext(false)
|
||||
return
|
||||
}
|
||||
JsActions.LOGIN_CHECK.inject(view)
|
||||
view.jsInject(JsActions.LOGIN_CHECK, JsAssets.HEADER_BADGES.maybe(webCore.baseEnum != null))
|
||||
onPageFinishedActions(url)
|
||||
}
|
||||
|
||||
@ -62,7 +65,7 @@ open class FrostWebViewClient(val webCore: FrostWebViewCore) : WebViewClient() {
|
||||
L.d("Page finished reveal")
|
||||
webCore.jsInject(CssHider.HEADER,
|
||||
Prefs.themeInjector,
|
||||
// JsAssets.CLICK_INTERCEPTOR,
|
||||
// JsAssets.CLICK_INTERCEPTOR,
|
||||
callback = {
|
||||
refreshObservable.onNext(false)
|
||||
})
|
||||
|
@ -41,6 +41,7 @@ class FrostWebViewCore @JvmOverloads constructor(
|
||||
val refreshObservable: PublishSubject<Boolean> // Only emits on page loads
|
||||
val titleObservable: BehaviorSubject<String> // Only emits on different non http titles
|
||||
|
||||
|
||||
var baseUrl: String? = null
|
||||
var baseEnum: FbTab? = null
|
||||
internal var frostWebClient: FrostWebViewClient? = null
|
||||
|
6
app/src/main/res/layout/view_badged_icon.xml
Normal file
6
app/src/main/res/layout/view_badged_icon.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
@ -41,4 +41,11 @@
|
||||
<string name="custom">Custom</string>
|
||||
<string name="frost_notifications">Frost Notifications</string>
|
||||
<string name="requires_custom_theme">Requires custom theme</string>
|
||||
|
||||
<string name="none">None</string>
|
||||
<string name="x_minutes">%d minutes</string>
|
||||
<string name="one_hour">1 hour</string>
|
||||
<string name="x_hours">%d hours</string>
|
||||
<string name="one_day">1 day</string>
|
||||
<string name="x_days">%d days</string>
|
||||
</resources>
|
||||
|
@ -6,18 +6,18 @@
|
||||
<item text="" />
|
||||
-->
|
||||
|
||||
<version title="v0.2"/>
|
||||
<item text="Removed unnecessary permissions" />
|
||||
<item text="" />
|
||||
<item text="" />
|
||||
<item text="" />
|
||||
<item text="" />
|
||||
|
||||
<version title="v0.1" />
|
||||
<item text="Initial Changelog" />
|
||||
<item text="Created core databases" />
|
||||
<item text="Implemented CSS/Js injectors" />
|
||||
<item text="Implemented ripple preferences" />
|
||||
<item text="" />
|
||||
<item text="" />
|
||||
<item text="" />
|
||||
<item text="" />
|
||||
<item text="" />
|
||||
<item text="" />
|
||||
<item text="" />
|
||||
<item text="" />
|
||||
<item text="" />
|
||||
<item text="Created multiple account caching" />
|
||||
<item text="Created web overlay" />
|
||||
</resources>
|
@ -1,7 +1,12 @@
|
||||
# Changelog
|
||||
|
||||
## v0.2
|
||||
* Removed unnecessary permissions
|
||||
|
||||
## v0.1
|
||||
* Initial Changelog
|
||||
* Created core databases
|
||||
* Implemented CSS/Js injectors
|
||||
* Implemented ripple preferences
|
||||
* Created multiple account caching
|
||||
* Created web overlay
|
||||
|
@ -16,11 +16,11 @@ APP_GROUP=com.pitchedapps
|
||||
MIN_SDK=21
|
||||
TARGET_SDK=26
|
||||
BUILD_TOOLS=26.0.0
|
||||
VERSION_CODE=1
|
||||
VERSION_NAME=0.1
|
||||
VERSION_CODE=2
|
||||
VERSION_NAME=0.2
|
||||
ANDROID_SUPPORT_LIBS=26.0.0-alpha1
|
||||
|
||||
KAU=9832aed0ea
|
||||
KAU=94defc1ab5
|
||||
MATERIAL_DRAWER=5.9.2
|
||||
MATERIAL_DRAWER_KT=1.0.2
|
||||
IICON_GOOGLE=3.0.1.0
|
||||
@ -34,6 +34,7 @@ JSOUP=1.10.2
|
||||
ANKO=0.10.1
|
||||
GLIDE=4.0.0-RC0
|
||||
RETROFIT=2.2.0
|
||||
EVENTBUS=3.0.0
|
||||
DBFLOW=4.0.2
|
||||
SQL_CIPHER=3.5.7
|
||||
OKHTTP_INTERCEPTOR=3.6.0
|
||||
|
Loading…
Reference in New Issue
Block a user