Sharing handling

Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
Mario Danic 2018-01-25 15:30:40 +01:00
parent e461a0c28a
commit 30aea14646
13 changed files with 452 additions and 62 deletions

View file

@ -111,7 +111,7 @@ dependencies {
debugImplementation "javax.transaction:transaction-api:1.1-rev-1"
implementation 'com.github.HITGIF:TextFieldBoxes:1.3.7'
implementation 'com.github.HITGIF:TextFieldBoxes:1.3.8'
implementation 'eu.davidea:flexible-adapter:5.0.0-rc4'
implementation 'eu.davidea:flexible-adapter-ui:1.0.0-b1'

View file

@ -0,0 +1,125 @@
/*
* Nextcloud Talk application
*
* @author Mario Danic
* Copyright (C) 2017 Mario Danic <mario@lovelyhq.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/>.
*/
package com.nextcloud.talk.adapters.items;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.nextcloud.talk.R;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import eu.davidea.flexibleadapter.FlexibleAdapter;
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem;
import eu.davidea.viewholders.FlexibleViewHolder;
public class AppItem extends AbstractFlexibleItem<AppItem.AppItemViewHolder> {
private String title;
private String packageName;
private String name;
@Nullable private Drawable drawable;
public AppItem(String title, String packageName, String name, @Nullable Drawable drawable) {
this.title = title;
this.packageName = packageName;
this.name = name;
this.drawable = drawable;
}
@Override
public boolean equals(Object o) {
if (o instanceof AppItem) {
AppItem inItem = (AppItem) o;
return title.equals(inItem.getTitle()) && packageName.equals(inItem.getPackageName()) && name.equals(inItem
.getName());
}
return false;
}
public String getTitle() {
return title;
}
public String getPackageName() {
return packageName;
}
public String getName() {
return name;
}
@Override
public int getLayoutRes() {
return R.layout.rv_item_app;
}
@Override
public AppItem.AppItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
return new AppItemViewHolder(view, adapter);
}
@Override
public void bindViewHolder(FlexibleAdapter adapter, AppItem.AppItemViewHolder holder, int position, List<Object> payloads) {
if (drawable != null) {
holder.iconImageView.setVisibility(View.VISIBLE);
holder.iconImageView.setImageDrawable(drawable);
} else {
holder.iconImageView.setVisibility(View.GONE);
}
if (position == 0) {
Spannable spannableString = new SpannableString(title);
spannableString.setSpan(new ForegroundColorSpan(NextcloudTalkApplication.getSharedApplication()
.getResources().getColor(R.color.colorPrimary)), 0,
spannableString.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
holder.appTitleTextView.setText(spannableString);
} else {
holder.appTitleTextView.setText(title);
}
}
static class AppItemViewHolder extends FlexibleViewHolder {
@BindView(R.id.icon_image_view)
public ImageView iconImageView;
@BindView(R.id.app_title_text_view)
public TextView appTitleTextView;
/**
* Default constructor.
*/
AppItemViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
}
}
}

View file

@ -72,7 +72,7 @@ public class MenuItem extends AbstractFlexibleItem<MenuItem.MenuItemViewHolder>
@Override
public void bindViewHolder(FlexibleAdapter adapter, MenuItem.MenuItemViewHolder holder, int position, List payloads) {
if (title.equals(NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_what))) {
if (position == 0) {
Spannable spannableString = new SpannableString(NextcloudTalkApplication.getSharedApplication()
.getString(R.string.nc_what));
spannableString.setSpan(new ForegroundColorSpan(NextcloudTalkApplication.getSharedApplication()

View file

@ -43,6 +43,7 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import com.bluelinelabs.conductor.RouterTransaction;
@ -416,6 +417,9 @@ public class CallsListController extends BaseController implements SearchView.On
if (bottomSheet == null) {
bottomSheet = new BottomSheet.Builder(getActivity()).setView(view).create();
if (bottomSheet.getWindow() != null) {
bottomSheet.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
}
}
bottomSheet.show();
@ -426,12 +430,14 @@ public class CallsListController extends BaseController implements SearchView.On
overridePushHandler(new NoOpControllerChangeHandler());
overridePopHandler(new NoOpControllerChangeHandler());
CallItem callItem = adapter.getItem(position);
Intent callIntent = new Intent(getActivity(), CallActivity.class);
BundleBuilder bundleBuilder = new BundleBuilder(new Bundle());
bundleBuilder.putString("roomToken", callItem.getModel().getToken());
bundleBuilder.putParcelable("userEntity", Parcels.wrap(userEntity));
callIntent.putExtras(bundleBuilder.build());
startActivity(callIntent);
if (callItem != null && getActivity() != null) {
Intent callIntent = new Intent(getActivity(), CallActivity.class);
BundleBuilder bundleBuilder = new BundleBuilder(new Bundle());
bundleBuilder.putString("roomToken", callItem.getModel().getToken());
bundleBuilder.putParcelable("userEntity", Parcels.wrap(userEntity));
callIntent.putExtras(bundleBuilder.build());
startActivity(callIntent);
}
return true;
}

View file

@ -20,6 +20,8 @@
package com.nextcloud.talk.controllers.bottomsheet;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.widget.DividerItemDecoration;
@ -30,13 +32,17 @@ import android.view.View;
import android.view.ViewGroup;
import com.bluelinelabs.conductor.RouterTransaction;
import com.kennyc.bottomsheet.adapters.AppAdapter;
import com.nextcloud.talk.R;
import com.nextcloud.talk.adapters.items.AppItem;
import com.nextcloud.talk.adapters.items.MenuItem;
import com.nextcloud.talk.api.models.json.rooms.Room;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.controllers.base.BaseController;
import com.nextcloud.talk.events.BottomSheetLockEvent;
import com.nextcloud.talk.utils.ShareUtils;
import com.nextcloud.talk.utils.bundle.BundleKeys;
import com.nextcloud.talk.utils.database.user.UserUtils;
import org.greenrobot.eventbus.EventBus;
import org.parceler.Parcels;
@ -60,13 +66,22 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
@Inject
EventBus eventBus;
@Inject
UserUtils userUtils;
private Room room;
private List<AbstractFlexibleItem> menuItems;
private FlexibleAdapter<AbstractFlexibleItem> adapter;
private boolean isShare;
private Intent shareIntent;
public CallMenuController(Bundle args) {
super(args);
this.room = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
if (args.containsKey(BundleKeys.KEY_IS_SHARE)) {
this.isShare = true;
}
}
@Override
@ -100,67 +115,109 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
));
}
private void prepareIntent() {
shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_SUBJECT, getResources().getString(R.string.nc_share_subject));
}
private void prepareMenu() {
menuItems = new ArrayList<>();
menuItems.add(new MenuItem(getResources().getString(R.string.nc_what), 0));
if (!isShare) {
menuItems.add(new MenuItem(getResources().getString(R.string.nc_what), 0));
menuItems.add(new MenuItem(getResources().getString(R.string.nc_leave), 1));
menuItems.add(new MenuItem(getResources().getString(R.string.nc_leave), 1));
if (room.isNameEditable()) {
menuItems.add(new MenuItem(getResources().getString(R.string.nc_rename), 2));
}
if (room.isNameEditable()) {
menuItems.add(new MenuItem(getResources().getString(R.string.nc_rename), 2));
}
if (room.canModerate()) {
if (!room.isPublic()) {
menuItems.add(new MenuItem(getResources().getString(R.string.nc_make_call_public), 3));
} else {
if (room.isHasPassword()) {
menuItems.add(new MenuItem(getResources().getString(R.string.nc_change_password), 4));
menuItems.add(new MenuItem(getResources().getString(R.string.nc_clear_password), 5));
if (room.canModerate()) {
if (!room.isPublic()) {
menuItems.add(new MenuItem(getResources().getString(R.string.nc_make_call_public), 3));
} else {
menuItems.add(new MenuItem(getResources().getString(R.string.nc_set_password), 6));
if (room.isHasPassword()) {
menuItems.add(new MenuItem(getResources().getString(R.string.nc_change_password), 4));
menuItems.add(new MenuItem(getResources().getString(R.string.nc_clear_password), 5));
} else {
menuItems.add(new MenuItem(getResources().getString(R.string.nc_set_password), 6));
}
}
}
}
if (room.isPublic()) {
menuItems.add(new MenuItem(getResources().getString(R.string.nc_share_link), 7));
if (room.canModerate()) {
menuItems.add(new MenuItem(getResources().getString(R.string.nc_make_call_private), 8));
if (room.isPublic()) {
menuItems.add(new MenuItem(getResources().getString(R.string.nc_share_link), 7));
if (room.canModerate()) {
menuItems.add(new MenuItem(getResources().getString(R.string.nc_make_call_private), 8));
}
}
}
if (room.isDeletable()) {
menuItems.add(new MenuItem(getResources().getString(R.string.nc_delete_call), 9));
if (room.isDeletable()) {
menuItems.add(new MenuItem(getResources().getString(R.string.nc_delete_call), 9));
}
} else {
prepareIntent();
List<AppAdapter.AppInfo> appInfoList = ShareUtils.getShareApps(getActivity(), shareIntent, null,
null);
menuItems.add(new AppItem(getResources().getString(R.string.nc_share_link_via), "", "",
null));
if (appInfoList != null) {
for (AppAdapter.AppInfo appInfo : appInfoList) {
menuItems.add(new AppItem(appInfo.title, appInfo.packageName, appInfo.name, appInfo.drawable));
}
}
}
}
@Override
public boolean onItemClick(int position) {
MenuItem menuItem = (MenuItem) adapter.getItem(position);
Bundle bundle = new Bundle();
if (menuItem != null) {
int tag = menuItem.getTag();
bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
if (tag == 5) {
room.setPassword("");
if (!isShare) {
MenuItem menuItem = (MenuItem) adapter.getItem(position);
if (menuItem != null) {
int tag = menuItem.getTag();
if (tag == 5) {
room.setPassword("");
}
if (tag > 0 && tag < 10) {
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, tag);
if (tag != 2 && tag != 4 && tag != 6 && tag != 7) {
eventBus.post(new BottomSheetLockEvent(false, 0, false));
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle)));
} else if (tag != 7) {
getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle)));
} else {
bundle.putBoolean(BundleKeys.KEY_IS_SHARE, true);
getRouter().pushController(RouterTransaction.with(new CallMenuController(bundle)));
}
}
}
bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
if (tag > 0 && tag < 10) {
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, tag);
if (tag != 2 && tag != 4 && tag != 6 && tag != 7) {
eventBus.post(new BottomSheetLockEvent(false, 0, false));
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle)));
} else if (tag != 7) {
getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle)));
} else if (position != 0) {
AppItem appItem = (AppItem) adapter.getItem(position);
if (appItem != null && getActivity() != null) {
if (!room.hasPassword) {
shareIntent.putExtra(Intent.EXTRA_TEXT, ShareUtils.getStringForIntent(getActivity(), null,
userUtils, room));
Intent intent = new Intent(shareIntent);
intent.setComponent(new ComponentName(appItem.getPackageName(), appItem.getName()));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getActivity().startActivity(intent);
} else {
// do nothing for now, this is share
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, 7);
bundle.putParcelable(BundleKeys.KEY_SHARE_INTENT, Parcels.wrap(shareIntent));
bundle.putString(BundleKeys.KEY_APP_ITEM_PACKAGE_NAME, appItem.getPackageName());
bundle.putString(BundleKeys.KEY_APP_ITEM_NAME, appItem.getName());
getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle)));
}
}
}
return true;
}
}

View file

@ -20,6 +20,8 @@
package com.nextcloud.talk.controllers.bottomsheet;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.text.Editable;
@ -36,7 +38,9 @@ import com.nextcloud.talk.api.models.json.rooms.Room;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.controllers.base.BaseController;
import com.nextcloud.talk.events.BottomSheetLockEvent;
import com.nextcloud.talk.utils.ShareUtils;
import com.nextcloud.talk.utils.bundle.BundleKeys;
import com.nextcloud.talk.utils.database.user.UserUtils;
import org.greenrobot.eventbus.EventBus;
import org.parceler.Parcels;
@ -65,13 +69,26 @@ public class EntryMenuController extends BaseController {
@Inject
EventBus eventBus;
@Inject
UserUtils userUtils;
private int operationCode;
private Room room;
private Intent shareIntent;
private String packageName;
private String name;
public EntryMenuController(Bundle args) {
super(args);
this.operationCode = args.getInt(BundleKeys.KEY_OPERATION_CODE);
this.room = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
if (args.containsKey(BundleKeys.KEY_SHARE_INTENT)) {
this.shareIntent = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_SHARE_INTENT));
}
this.name = args.getString(BundleKeys.KEY_APP_ITEM_NAME, "");
this.packageName = args.getString(BundleKeys.KEY_APP_ITEM_PACKAGE_NAME, "");
}
@Override
@ -81,17 +98,28 @@ public class EntryMenuController extends BaseController {
@OnClick(R.id.ok_button)
public void onProceedButtonClick() {
eventBus.post(new BottomSheetLockEvent(false, 0, false));
if (operationCode != 7) {
eventBus.post(new BottomSheetLockEvent(false, 0, false));
Bundle bundle = new Bundle();
if (operationCode == 4 || operationCode == 6) {
room.setPassword(editText.getText().toString());
Bundle bundle = new Bundle();
if (operationCode == 4 || operationCode == 6) {
room.setPassword(editText.getText().toString());
} else {
room.setName(editText.getText().toString());
}
bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, operationCode);
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle)));
} else {
room.setName(editText.getText().toString());
if (getActivity() != null) {
shareIntent.putExtra(Intent.EXTRA_TEXT, ShareUtils.getStringForIntent(getActivity(),
editText.getText().toString(), userUtils, room));
Intent intent = new Intent(shareIntent);
intent.setComponent(new ComponentName(packageName, name));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getActivity().startActivity(intent);
}
}
bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, operationCode);
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle)));
}
@Override
@ -142,23 +170,23 @@ public class EntryMenuController extends BaseController {
}
});
String helperText = "";
String labelText = "";
switch (operationCode) {
case 2:
helperText = getResources().getString(R.string.nc_call_name);
labelText = getResources().getString(R.string.nc_call_name);
break;
case 4:
helperText = getResources().getString(R.string.nc_new_password);
labelText = getResources().getString(R.string.nc_new_password);
break;
case 6:
helperText = getResources().getString(R.string.nc_password);
case 7:
labelText = getResources().getString(R.string.nc_password);
break;
default:
break;
}
textFieldBoxes.setHelperText(helperText);
textFieldBoxes.setLabelText(labelText);
editText.requestFocus();
}
}

View file

@ -150,7 +150,7 @@ public class OperationsMenuController extends BaseController {
.subscribe(operationsObserver);
break;
case 7:
// Operation 6 is sharing, so we handle this differently
// Operation 7 is sharing, so we handle this differently
break;
case 8:
ncApi.makeRoomPrivate(credentials, ApiHelper.getUrlForRoomVisibility(userEntity.getBaseUrl(), room

View file

@ -0,0 +1,112 @@
/*
* Nextcloud Talk application
*
* @author Mario Danic
* Copyright (C) 2017 Mario Danic <mario@lovelyhq.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/>.
*
* Part of the code in ShareUtils was inspired by BottomSheet under the Apache licence
* located here: https://github.com/Kennyc1012/BottomSheet/blob/master/library/src/main/java/com/kennyc/bottomsheet/BottomSheet.java#L425
*/
package com.nextcloud.talk.utils;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import com.kennyc.bottomsheet.adapters.AppAdapter;
import com.nextcloud.talk.R;
import com.nextcloud.talk.api.models.json.rooms.Room;
import com.nextcloud.talk.persistence.entities.UserEntity;
import com.nextcloud.talk.utils.database.user.UserUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class ShareUtils {
private static final String TAG = "ShareUtils";
public static String getStringForIntent(Context context, @Nullable String password, UserUtils userUtils, Room
room) {
UserEntity userEntity = userUtils.getCurrentUser();
String shareString = "";
if (userEntity != null && context != null) {
shareString = String.format(context.getResources().getString(R.string.nc_share_text),
userEntity.getBaseUrl(), room.getToken());
if (!TextUtils.isEmpty(password)) {
shareString += String.format(context.getResources().getString(R.string.nc_share_text_pass), password);
}
shareString += String.format(context.getResources().getString(R.string.nc_talk_soon), userEntity
.getDisplayName()
);
}
return shareString;
}
public static List<AppAdapter.AppInfo> getShareApps(Context context, Intent intent,
@Nullable Set<String> appsFilter, @Nullable Set<String> toExclude) {
if (context == null || intent == null) return null;
PackageManager manager = context.getPackageManager();
List<ResolveInfo> apps = manager.queryIntentActivities(intent, 0);
if (apps != null && !apps.isEmpty()) {
List<AppAdapter.AppInfo> appResources = new ArrayList<>(apps.size());
boolean shouldCheckPackages = appsFilter != null && !appsFilter.isEmpty();
for (ResolveInfo resolveInfo : apps) {
String packageName = resolveInfo.activityInfo.packageName;
if (shouldCheckPackages && !appsFilter.contains(packageName)) {
continue;
}
String title = resolveInfo.loadLabel(manager).toString();
String name = resolveInfo.activityInfo.name;
Drawable drawable = resolveInfo.loadIcon(manager);
appResources.add(new AppAdapter.AppInfo(title, packageName, name, drawable));
}
if (toExclude != null && !toExclude.isEmpty()) {
List<AppAdapter.AppInfo> toRemove = new ArrayList<>();
for (AppAdapter.AppInfo appInfo : appResources) {
if (toExclude.contains(appInfo.packageName)) {
toRemove.add(appInfo);
}
}
if (!toRemove.isEmpty()) appResources.removeAll(toRemove);
}
return appResources;
}
return null;
}
}

View file

@ -28,4 +28,8 @@ public class BundleKeys {
public static final String KEY_ORIGINAL_PROTOCOL = "KEY_ORIGINAL_PROTOCOL";
public static final String KEY_ROOM = "KEY_ROOM";
public static final String KEY_OPERATION_CODE = "KEY_OPERATION_CODE";
public static final String KEY_IS_SHARE = "KEY_IS_SHARE";
public static final String KEY_SHARE_INTENT = "KEY_SHARE_INTENT";
public static final String KEY_APP_ITEM_PACKAGE_NAME = "KEY_APP_ITEM_PACKAGE_NAME";
public static final String KEY_APP_ITEM_NAME = "KEY_APP_ITEM_NAME";
}

View file

@ -28,7 +28,7 @@
<studio.carbonylgroup.textfieldboxes.TextFieldBoxes
android:id="@+id/text_field_boxes"
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_height="96dp"
android:layout_marginEnd="@dimen/activity_horizontal_margin"
android:layout_marginStart="@dimen/activity_horizontal_margin"
app:errorColor="@color/nc_darkRed"

View file

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Nextcloud Talk application
~
~ @author Mario Danic
~ Copyright (C) 2017 Mario Danic <mario@lovelyhq.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:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginTop="16dp"
android:background="@color/nc_white_color"
android:orientation="horizontal">
<ImageView
android:id="@+id/icon_image_view"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_centerVertical="true"
android:layout_marginStart="16dp"/>
<TextView
android:id="@+id/app_title_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_centerVertical="true"
android:layout_toEndOf="@id/icon_image_view"
android:textAlignment="center"
android:textSize="12sp"
tools:text="App title"/>
</RelativeLayout>

View file

@ -22,13 +22,16 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/menu_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:textSize="12sp"/>
</RelativeLayout>

View file

@ -77,6 +77,7 @@
<string name="nc_change_password">Change a password</string>
<string name="nc_clear_password">Clear password</string>
<string name="nc_share_link">Share link</string>
<string name="nc_share_link_via">Share link via</string>
<string name="nc_make_call_public">Make call public</string>
<string name="nc_make_call_private">Make call private</string>
<string name="nc_delete_call">Delete call</string>
@ -110,5 +111,9 @@
<string name="nc_call_name">Call name</string>
<string name="nc_proceed">Proceed</string>
<string name="nc_call_name_is_same">The name you entered is the same as the existing one</string>
<string name="nc_share_text">Hello,\n\nI would like you to join a call with me.\n\nYou can join this call via
%1$s/index.php/call/%2$s</string>
<string name="nc_talk_soon">\n\nTalk soon,\n %1$s</string>
<string name="nc_share_subject">Call invitation</string>
<string name="nc_share_text_pass">\n\nPassword for the call is: %1$s</string>
</resources>