improved launch presentations
This commit is contained in:
parent
812a44512c
commit
d2fccb6fc7
|
@ -143,8 +143,29 @@ public class LaunchPresentation {
|
|||
@JsonField(name = "url")
|
||||
String url;
|
||||
|
||||
@JsonField(name = "density")
|
||||
float density;
|
||||
|
||||
@JsonField(name = "width")
|
||||
int width;
|
||||
|
||||
@JsonField(name = "height")
|
||||
int height;
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public float getDensity() {
|
||||
return density;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import android.support.annotation.StyleRes
|
|||
import android.support.v4.view.ViewCompat
|
||||
import android.support.v7.app.TwilightManagerAccessor
|
||||
import android.view.View
|
||||
import android.view.View.MeasureSpec
|
||||
import android.widget.Toast
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.Priority
|
||||
|
@ -54,6 +55,7 @@ import org.mariotaku.twidere.constant.lastLaunchTimeKey
|
|||
import org.mariotaku.twidere.constant.promotionsEnabledKey
|
||||
import org.mariotaku.twidere.constant.themeColorKey
|
||||
import org.mariotaku.twidere.constant.themeKey
|
||||
import org.mariotaku.twidere.extension.model.displayingScore
|
||||
import org.mariotaku.twidere.extension.model.hasInvalidAccount
|
||||
import org.mariotaku.twidere.extension.model.shouldShow
|
||||
import org.mariotaku.twidere.model.presentation.LaunchPresentation
|
||||
|
@ -138,10 +140,10 @@ open class MainActivity : ChameleonActivity(), IBaseActivity<MainActivity> {
|
|||
}
|
||||
|
||||
ViewCompat.setOnApplyWindowInsetsListener(main) lambda@ { _, insets ->
|
||||
main.setPadding(0, 0, 0, insets.systemWindowInsetBottom)
|
||||
main.setPadding(0, 0, insets.systemWindowInsetRight,
|
||||
insets.systemWindowInsetBottom)
|
||||
|
||||
controlOverlay.setPadding(insets.systemWindowInsetLeft, insets.systemWindowInsetTop,
|
||||
insets.systemWindowInsetRight, 0)
|
||||
controlOverlay.setPadding(0, insets.systemWindowInsetTop, 0, 0)
|
||||
return@lambda insets.consumeSystemWindowInsets()
|
||||
}
|
||||
ViewSupport.setOutlineProvider(skipPresentation, ViewOutlineProviderCompat.BACKGROUND)
|
||||
|
@ -163,10 +165,9 @@ open class MainActivity : ChameleonActivity(), IBaseActivity<MainActivity> {
|
|||
}
|
||||
val presentation = jsonCache.getList(RefreshLaunchPresentationsTask.JSON_CACHE_KEY,
|
||||
LaunchPresentation::class.java)?.firstOrNull {
|
||||
it.shouldShow()
|
||||
it.shouldShow(this)
|
||||
}
|
||||
if (presentation != null) {
|
||||
displayPresentation(presentation)
|
||||
if (presentation != null && displayPresentation(presentation)) {
|
||||
launchLater()
|
||||
} else {
|
||||
launchDirectly()
|
||||
|
@ -225,12 +226,24 @@ open class MainActivity : ChameleonActivity(), IBaseActivity<MainActivity> {
|
|||
isNightBackup = nightState
|
||||
}
|
||||
|
||||
private fun displayPresentation(presentation: LaunchPresentation) {
|
||||
private fun displayPresentation(presentation: LaunchPresentation): Boolean {
|
||||
skipPresentation.visibility = View.VISIBLE
|
||||
controlOverlay.tag = presentation
|
||||
Glide.with(this).load(presentation.images.first().url)
|
||||
|
||||
val dm = resources.displayMetrics
|
||||
main.measure(MeasureSpec.makeMeasureSpec(dm.widthPixels,
|
||||
MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dm.heightPixels,
|
||||
MeasureSpec.EXACTLY))
|
||||
|
||||
val width = presentationView.measuredWidth
|
||||
val height = presentationView.measuredHeight
|
||||
val images = presentation.images.sortedByDescending { it.displayingScore(dm.density, width, height) }
|
||||
val image = images.firstOrNull() ?: return false
|
||||
|
||||
Glide.with(this).load(image.url)
|
||||
.priority(Priority.HIGH)
|
||||
.into(presentationView)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun launchDirectly() {
|
||||
|
|
|
@ -19,17 +19,16 @@
|
|||
|
||||
package org.mariotaku.twidere.extension.model
|
||||
|
||||
import android.content.Context
|
||||
import android.support.v4.os.LocaleListCompat
|
||||
import org.mariotaku.ktextension.localesCompat
|
||||
import org.mariotaku.twidere.model.presentation.LaunchPresentation
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2017/8/20.
|
||||
*/
|
||||
|
||||
fun LaunchPresentation.shouldShow(): Boolean {
|
||||
fun LaunchPresentation.shouldShow(context: Context): Boolean {
|
||||
// Check language
|
||||
val locale = Locale.getDefault()
|
||||
if (locales != null && locales.none { it.matches(locale) }) {
|
||||
val userLocales = context.resources.configuration.localesCompat
|
||||
if (locales != null && locales.none { it.matchesAny(userLocales) }) {
|
||||
return false
|
||||
}
|
||||
// Check date/time
|
||||
|
@ -54,3 +53,33 @@ fun LaunchPresentation.Locale.matches(locale: Locale): Boolean {
|
|||
}
|
||||
return country == locale.country
|
||||
}
|
||||
|
||||
fun LaunchPresentation.Locale.matchesAny(locales: LocaleListCompat): Boolean {
|
||||
return (0 until locales.size()).any { matches(locales[it]) }
|
||||
}
|
||||
|
||||
fun LaunchPresentation.Image.displayingScore(viewDensity: Float, viewWidth: Int,
|
||||
viewHeight: Int): Int {
|
||||
if (viewWidth == 0 || viewHeight == 0) return 0
|
||||
var score = 0
|
||||
// Compute size scores
|
||||
score += when {
|
||||
viewWidth == width && viewHeight <= height -> 100
|
||||
viewHeight == height && viewWidth <= width -> 100
|
||||
viewWidth < width && viewHeight < height -> {
|
||||
val diffW = (width / viewWidth.toFloat() - 1).coerceAtMost(0.5f)
|
||||
val diffH = (height / viewHeight.toFloat() - 1).coerceAtMost(0.5f)
|
||||
100 - Math.round(diffH * 100) - Math.round(diffW * 100)
|
||||
}
|
||||
else -> {
|
||||
val diffW = (width / viewWidth.toFloat() - 1).coerceAtMost(0.5f)
|
||||
val diffH = (height / viewHeight.toFloat() - 1).coerceAtMost(0.5f)
|
||||
100 - Math.round(diffH * 50) - Math.round(diffW * 50)
|
||||
}
|
||||
}
|
||||
if (this.density != 0f) {
|
||||
score += 100 - Math.round(Math.abs(this.density / viewDensity - 1).coerceAtMost(1f))
|
||||
}
|
||||
return score
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ package org.mariotaku.twidere.task.filter
|
|||
import android.content.Context
|
||||
import org.mariotaku.restfu.annotation.method.GET
|
||||
import org.mariotaku.restfu.http.HttpRequest
|
||||
import org.mariotaku.twidere.BuildConfig
|
||||
import org.mariotaku.twidere.model.presentation.LaunchPresentation
|
||||
import org.mariotaku.twidere.task.BaseAbstractTask
|
||||
import org.mariotaku.twidere.util.JsonSerializer
|
||||
|
@ -33,10 +34,14 @@ import java.io.IOException
|
|||
*/
|
||||
class RefreshLaunchPresentationsTask(context: Context) : BaseAbstractTask<Unit?, Boolean, (Boolean) -> Unit>(context) {
|
||||
override fun doLongOperation(params: Unit?): Boolean {
|
||||
val request = HttpRequest.Builder()
|
||||
.method(GET.METHOD)
|
||||
.url("https://twidere.mariotaku.org/assets/data/launch_presentations.json")
|
||||
.build()
|
||||
val builder = HttpRequest.Builder()
|
||||
builder.method(GET.METHOD)
|
||||
if (BuildConfig.DEBUG) {
|
||||
builder.url("https://twidere.mariotaku.org/assets/data/launch_presentations_debug.json")
|
||||
} else {
|
||||
builder.url("https://twidere.mariotaku.org/assets/data/launch_presentations.json")
|
||||
}
|
||||
val request = builder.build()
|
||||
try {
|
||||
val presentations = restHttpClient.newCall(request).execute().use {
|
||||
if (!it.isSuccessful) return@use null
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Twidere - Twitter client for Android
|
||||
~
|
||||
~ Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
~
|
||||
~ This program is free software: you can redistribute it and/or modify
|
||||
~ it under the terms of the GNU General Public License as published by
|
||||
~ the Free Software Foundation, either version 3 of the License, or
|
||||
~ (at your option) any later version.
|
||||
~
|
||||
~ This program is distributed in the hope that it will be useful,
|
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
~ GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/presentationView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toLeftOf="@+id/logoContainer"
|
||||
android:layout_toStartOf="@+id/logoContainer"
|
||||
android:scaleType="centerCrop"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/logoContainer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:gravity="center"
|
||||
android:minWidth="108dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/appIcon"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:src="@mipmap/ic_launcher"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/controlOverlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignEnd="@+id/presentationView"
|
||||
android:layout_alignRight="@+id/presentationView">
|
||||
|
||||
<Button
|
||||
android:id="@+id/skipPresentation"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top|end"
|
||||
android:layout_marginEnd="@dimen/element_spacing_large"
|
||||
android:layout_marginRight="@dimen/element_spacing_large"
|
||||
android:layout_marginTop="@dimen/element_spacing_large"
|
||||
android:background="@drawable/bg_btn_launch_presentation_skip"
|
||||
android:minHeight="36dp"
|
||||
android:minWidth="56dp"
|
||||
android:text="@string/action_skip"
|
||||
android:textColor="@android:color/white"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
</FrameLayout>
|
||||
</RelativeLayout>
|
|
@ -47,8 +47,8 @@
|
|||
android:id="@+id/appIcon"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
tools:src="@mipmap/ic_launcher"
|
||||
tools:ignore="ContentDescription"/>
|
||||
tools:ignore="ContentDescription"
|
||||
tools:src="@mipmap/ic_launcher"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -74,7 +74,8 @@
|
|||
<FrameLayout
|
||||
android:id="@+id/controlOverlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignBottom="@+id/presentationView">
|
||||
|
||||
<Button
|
||||
android:id="@+id/skipPresentation"
|
||||
|
|
Loading…
Reference in New Issue