Themes header: plain background color and logo, if available

Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>
This commit is contained in:
tobiasKaminsky 2021-01-08 07:54:55 +01:00
parent fa8d42a252
commit fd9e0e2f69
No known key found for this signature in database
GPG key ID: 0E00D4D47D0C5AF7
10 changed files with 355 additions and 8 deletions

View file

@ -2041,6 +2041,8 @@ public class FileDataStorageManager {
capability.getServerBackground());
contentValues.put(ProviderTableMeta.CAPABILITIES_SERVER_SLOGAN,
capability.getServerSlogan());
contentValues.put(ProviderTableMeta.CAPABILITIES_SERVER_LOGO,
capability.getServerLogo());
contentValues.put(ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION,
capability.getEndToEndEncryption().getValue());
contentValues.put(ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_DEFAULT,
@ -2185,6 +2187,7 @@ public class FileDataStorageManager {
capability.setServerElementColor(getString(cursor, ProviderTableMeta.CAPABILITIES_SERVER_ELEMENT_COLOR));
capability.setServerBackground(getString(cursor, ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_URL));
capability.setServerSlogan(getString(cursor, ProviderTableMeta.CAPABILITIES_SERVER_SLOGAN));
capability.setServerLogo(getString(cursor, ProviderTableMeta.CAPABILITIES_SERVER_LOGO));
capability.setEndToEndEncryption(getBoolean(cursor, ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION));
capability.setServerBackgroundDefault(
getBoolean(cursor, ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_DEFAULT));

View file

@ -35,7 +35,7 @@ import java.util.List;
*/
public class ProviderMeta {
public static final String DB_NAME = "filelist";
public static final int DB_VERSION = 61;
public static final int DB_VERSION = 62;
private ProviderMeta() {
// No instance
@ -211,6 +211,7 @@ public class ProviderMeta {
public static final String CAPABILITIES_SERVER_ELEMENT_COLOR = "server_element_color";
public static final String CAPABILITIES_SERVER_BACKGROUND_URL = "background_url";
public static final String CAPABILITIES_SERVER_SLOGAN = "server_slogan";
public static final String CAPABILITIES_SERVER_LOGO = "server_logo";
public static final String CAPABILITIES_SERVER_BACKGROUND_DEFAULT = "background_default";
public static final String CAPABILITIES_SERVER_BACKGROUND_PLAIN = "background_plain";
public static final String CAPABILITIES_END_TO_END_ENCRYPTION = "end_to_end_encryption";

View file

@ -783,6 +783,7 @@ public class FileContentProvider extends ContentProvider {
+ ProviderTableMeta.CAPABILITIES_SERVER_TEXT_COLOR + TEXT
+ ProviderTableMeta.CAPABILITIES_SERVER_ELEMENT_COLOR + TEXT
+ ProviderTableMeta.CAPABILITIES_SERVER_SLOGAN + TEXT
+ ProviderTableMeta.CAPABILITIES_SERVER_LOGO + TEXT
+ ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_URL + TEXT
+ ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION + INTEGER
+ ProviderTableMeta.CAPABILITIES_ACTIVITY + INTEGER
@ -2305,6 +2306,27 @@ public class FileContentProvider extends ContentProvider {
if (!upgraded) {
Log_OC.i(SQL, String.format(Locale.ENGLISH, UPGRADE_VERSION_MSG, oldVersion, newVersion));
}
if (oldVersion < 62 && newVersion >= 62) {
Log_OC.i(SQL, "Entering in the #62 add logo to capability");
db.beginTransaction();
try {
db.execSQL(ALTER_TABLE + ProviderTableMeta.CAPABILITIES_TABLE_NAME +
ADD_COLUMN + ProviderTableMeta.CAPABILITIES_SERVER_LOGO + " TEXT ");
// force refresh
db.execSQL("UPDATE capabilities SET etag = '' WHERE 1=1");
upgraded = true;
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
if (!upgraded) {
Log_OC.i(SQL, String.format(Locale.ENGLISH, UPGRADE_VERSION_MSG, oldVersion, newVersion));
}
}
}
}

View file

@ -33,21 +33,34 @@ import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewGroup.MarginLayoutParams;
import android.webkit.URLUtil;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.bumptech.glide.GenericRequestBuilder;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.model.StreamEncoder;
import com.bumptech.glide.load.resource.file.FileToStreamDecoder;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.SimpleTarget;
import com.google.android.material.button.MaterialButton;
@ -93,6 +106,9 @@ import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.DrawerMenuUtil;
import com.owncloud.android.utils.FilesSyncHelper;
import com.owncloud.android.utils.svg.MenuSimpleTarget;
import com.owncloud.android.utils.svg.SVGorImage;
import com.owncloud.android.utils.svg.SvgOrImageBitmapTranscoder;
import com.owncloud.android.utils.svg.SvgOrImageDecoder;
import com.owncloud.android.utils.theme.ThemeBarUtils;
import com.owncloud.android.utils.theme.ThemeColorUtils;
import com.owncloud.android.utils.theme.ThemeDrawableUtils;
@ -104,6 +120,7 @@ import org.greenrobot.eventbus.ThreadMode;
import org.parceler.Parcels;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@ -212,8 +229,7 @@ public abstract class DrawerActivity extends ToolbarActivity
// Setting up drawer header
mNavigationViewHeader = mNavigationView.getHeaderView(0);
FrameLayout drawerHeader = mNavigationViewHeader.findViewById(R.id.drawer_header_view);
setupDrawerHeader(drawerHeader);
updateHeader();
setupDrawerMenu(mNavigationView);
getAndDisplayUserQuota();
@ -278,6 +294,73 @@ public abstract class DrawerActivity extends ToolbarActivity
ThemeBarUtils.colorProgressBar(mQuotaProgressBar, ThemeColorUtils.primaryColor(this));
}
public void updateHeader() {
if (getAccount() != null &&
getStorageManager().getCapability(getAccount().name).getServerBackground() != null) {
OCCapability capability = getStorageManager().getCapability(getAccount().name);
String logo = capability.getServerLogo();
int primaryColor = ThemeColorUtils.primaryColor(getAccount(), false, this);
// set background to primary color
LinearLayout drawerHeader = mNavigationViewHeader.findViewById(R.id.drawer_header_view);
drawerHeader.setBackgroundColor(ThemeColorUtils.unchangedPrimaryColor(getAccount(), this));
if (!TextUtils.isEmpty(logo) && URLUtil.isValidUrl(logo)) {
// background image
GenericRequestBuilder<Uri, InputStream, SVGorImage, Bitmap> requestBuilder = Glide.with(this)
.using(Glide.buildStreamModelLoader(Uri.class, this), InputStream.class)
.from(Uri.class)
.as(SVGorImage.class)
.transcode(new SvgOrImageBitmapTranscoder(128, 128), Bitmap.class)
.sourceEncoder(new StreamEncoder())
.cacheDecoder(new FileToStreamDecoder<>(new SvgOrImageDecoder()))
.decoder(new SvgOrImageDecoder());
// background image
SimpleTarget target = new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {
Drawable[] drawables = {new ColorDrawable(primaryColor), new BitmapDrawable(resource)};
LayerDrawable layerDrawable = new LayerDrawable(drawables);
String name = capability.getServerName();
setDrawerHeaderLogo(layerDrawable, name);
}
};
requestBuilder
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.load(Uri.parse(logo))
.into(target);
}
}
}
private void setDrawerHeaderLogo(Drawable drawable, String name) {
ImageView imageHeader = mNavigationViewHeader.findViewById(R.id.drawer_header_logo);
imageHeader.setImageDrawable(drawable);
imageHeader.setScaleType(ImageView.ScaleType.FIT_START);
imageHeader.setAdjustViewBounds(true);
imageHeader.setMaxWidth(DisplayUtils.convertDpToPixel(100f, this));
MarginLayoutParams oldParam = (MarginLayoutParams) imageHeader.getLayoutParams();
MarginLayoutParams params = new MarginLayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.MATCH_PARENT);
params.leftMargin = oldParam.leftMargin;
params.rightMargin = oldParam.rightMargin;
imageHeader.setLayoutParams(new LinearLayout.LayoutParams(params));
if (!TextUtils.isEmpty(name)) {
TextView serverName = mNavigationViewHeader.findViewById(R.id.drawer_header_server_name);
serverName.setText(name);
serverName.setTextColor(ThemeColorUtils.unchangedFontColor(this));
}
}
/**
* setup drawer header, basically the logo color
*/

View file

@ -0,0 +1,47 @@
/*
*
* Nextcloud Android client application
*
* @author Tobias Kaminsky
* Copyright (C) 2021 Tobias Kaminsky
* Copyright (C) 2021 Nextcloud GmbH
*
* Adapted from https://stackoverflow.com/a/54523482
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.owncloud.android.utils.svg;
import android.graphics.Bitmap;
import com.caverock.androidsvg.SVG;
public class SVGorImage {
private SVG svg;
private Bitmap bitmap;
public SVGorImage(SVG svg, Bitmap bitmap) {
this.svg = svg;
this.bitmap = bitmap;
}
public SVG getSVG() {
return svg;
}
public Bitmap getBitmap() {
return bitmap;
}
}

View file

@ -0,0 +1,81 @@
/*
*
* Nextcloud Android client application
*
* @author Tobias Kaminsky
* Copyright (C) 2021 Tobias Kaminsky
* Copyright (C) 2021 Nextcloud GmbH
*
* Adapted from https://stackoverflow.com/a/54523482
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.owncloud.android.utils.svg;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.resource.SimpleResource;
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
import com.caverock.androidsvg.SVG;
import com.caverock.androidsvg.SVGParseException;
import com.owncloud.android.lib.common.utils.Log_OC;
/**
* Convert the {@link SVG}'s internal representation to a Bitmap.
*/
public class SvgOrImageBitmapTranscoder implements ResourceTranscoder<SVGorImage, Bitmap> {
private int width;
private int height;
public SvgOrImageBitmapTranscoder(int width, int height) {
this.width = width;
this.height = height;
}
@Override
public Resource<Bitmap> transcode(Resource<SVGorImage> toTranscode) {
SVGorImage svGorImage = toTranscode.get();
if (svGorImage.getSVG() != null) {
SVG svg = svGorImage.getSVG();
try {
svg.setDocumentHeight("100%");
svg.setDocumentWidth("100%");
} catch (SVGParseException e) {
Log_OC.e(this, "Could not set document size. Output might have wrong size");
}
// Create a canvas to draw onto
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
// Render our document onto our canvas
svg.renderToCanvas(canvas);
return new SimpleResource<>(bitmap);
} else {
Bitmap bitmap = svGorImage.getBitmap();
return new SimpleResource<>(bitmap);
}
}
@Override
public String getId() {
return "";
}
}

View file

@ -0,0 +1,77 @@
/*
* Nextcloud Android client application
*
* Copyright 2014 Google, Inc. All rights reserved.
* Licenced under the BSD licence
*
* Borrowed from:
* https://github.com/bumptech/glide/blob/master/samples/svg/src/main/java/com/bumptech/glide/samples/svg/
* SvgDecoder.java
*
* Adapted from https://stackoverflow.com/a/54523482
*
*/
package com.owncloud.android.utils.svg;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.resource.SimpleResource;
import com.caverock.androidsvg.PreserveAspectRatio;
import com.caverock.androidsvg.SVG;
import com.caverock.androidsvg.SVGParseException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* Decodes an SVG internal representation from an {@link InputStream}.
*/
public class SvgOrImageDecoder implements ResourceDecoder<InputStream, SVGorImage> {
private int height = -1;
private int width = -1;
public SvgOrImageDecoder(int height, int width) {
this.height = height;
this.width = width;
}
public SvgOrImageDecoder() {
// empty constructor
}
public Resource<SVGorImage> decode(InputStream source, int w, int h) throws IOException {
byte[] array = new byte[source.available()];
source.read(array);
ByteArrayInputStream svgInputStream = new ByteArrayInputStream(array.clone());
ByteArrayInputStream pngInputStream = new ByteArrayInputStream(array.clone());
try {
SVG svg = SVG.getFromInputStream(svgInputStream);
source.close();
pngInputStream.close();
if (width > 0) {
svg.setDocumentWidth(width);
}
if (height > 0) {
svg.setDocumentHeight(height);
}
svg.setDocumentPreserveAspectRatio(PreserveAspectRatio.LETTERBOX);
return new SimpleResource<>(new SVGorImage(svg, null));
} catch (SVGParseException ex) {
Bitmap bitmap = BitmapFactory.decodeStream(pngInputStream);
return new SimpleResource<>(new SVGorImage(null, bitmap));
}
}
@Override
public String getId() {
return "SvgDecoder.com.owncloud.android";
}
}

View file

@ -316,4 +316,24 @@ public final class ThemeColorUtils {
public static String primaryColorToHexString(Context context) {
return String.format("#%06X", 0xFFFFFF & primaryColor(context, true));
}
public static int unchangedPrimaryColor(Account account, Context context) {
try {
return Color.parseColor(getCapability(account, context).getServerColor());
} catch (Exception e) {
return context.getResources().getColor(R.color.primary);
}
}
public static int unchangedFontColor(Context context) {
try {
return Color.parseColor(getCapability(context).getServerTextColor());
} catch (Exception e) {
if (darkTheme(context)) {
return Color.WHITE;
} else {
return Color.BLACK;
}
}
}
}

View file

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!--
<?xml version="1.0" encoding="utf-8"?>
<!--
Nextcloud Android client application
Copyright (C) 2016 Andy Scherzinger
@ -18,19 +19,31 @@
You should have received a copy of the GNU Affero General Public
License along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_header_view"
android:layout_width="match_parent"
android:layout_height="@dimen/drawer_header_height"
android:fitsSystemWindows="true">
android:fitsSystemWindows="true"
android:orientation="horizontal"
tools:background="@color/primary">
<ImageView
android:id="@+id/drawer_header_logo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/standard_margin"
android:contentDescription="@string/empty"
android:contentDescription="@null"
android:scaleType="fitCenter"
android:src="@drawable/nextcloud_logo" />
</FrameLayout>
<TextView
android:id="@+id/drawer_header_server_name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:ellipsize="middle"
android:gravity="center_vertical"
android:textSize="18sp"
android:textStyle="bold"
tools:text="Custom Server Name" />
</LinearLayout>