Merge pull request #12880 from nextcloud/bugfix/assistant-ui-ux

Assistant Feature UI/UX Fixes
This commit is contained in:
Tobias Kaminsky 2024-04-17 09:33:11 +02:00 коммит произвёл GitHub
Родитель df0bab3c17 0609caadb3
Коммит f050c340af
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
16 изменённых файлов: 479 добавлений и 155 удалений

Просмотреть файл

@ -42,8 +42,8 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.nextcloud.client.assistant.component.AddTaskAlertDialog
import com.nextcloud.client.assistant.component.CenterText
import com.nextcloud.client.assistant.component.TaskTypesRow
import com.nextcloud.client.assistant.component.TaskView
import com.nextcloud.client.assistant.taskTypes.TaskTypesRow
import com.nextcloud.client.assistant.task.TaskView
import com.nextcloud.client.assistant.repository.AssistantMockRepository
import com.nextcloud.ui.composeActivity.ComposeActivity
import com.nextcloud.ui.composeComponents.alertDialog.SimpleAlertDialog

Просмотреть файл

@ -35,3 +35,8 @@ fun Task.statusData(): Pair<Int, Int> {
}
}
}
// TODO add
fun Task.completionDateRepresentation(): String {
return completionExpectedAt ?: "TODO IMPLEMENT IT"
}

Просмотреть файл

@ -7,12 +7,14 @@
*/
package com.nextcloud.client.assistant.repository
import com.nextcloud.utils.extensions.getRandomString
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.resources.assistant.model.Task
import com.owncloud.android.lib.resources.assistant.model.TaskList
import com.owncloud.android.lib.resources.assistant.model.TaskType
import com.owncloud.android.lib.resources.assistant.model.TaskTypes
@Suppress("MagicNumber")
class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : AssistantRepositoryType {
override fun getTaskTypes(): RemoteOperationResult<TaskTypes> {
return RemoteOperationResult<TaskTypes>(RemoteOperationResult.ResultCode.OK).apply {
@ -41,16 +43,8 @@ class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : Ass
null,
"12",
"",
"Give me some text",
"Lorem Ipsum is simply dummy text of the printing and typesetting industry. " +
"Lorem Ipsum has been the industry's standard dummy text ever since the 1500s," +
" when an unknown printer took a galley of type and scrambled it to make a type" +
" specimen book. It has survived not only five centuries, " +
"but also the leap into electronic typesetting, remaining essentially unchanged." +
" It was popularised in the 1960s with the release of Letraset sheets containing " +
"Lorem Ipsum passages, and more recently with desktop publishing software like Aldus" +
" PageMaker including versions of Lorem Ipsum",
"",
"Give me some long text 1",
"Lorem ipsum".getRandomString(100),
""
),
Task(
@ -60,7 +54,62 @@ class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : Ass
"12",
"",
"Give me some text 2",
"Lorem Ipsum is simply dummy text of the printing and typesetting industry.",
"Lorem".getRandomString(100),
"",
""
),
Task(
3,
"FreePrompt",
null,
"12",
"",
"Give me some text 3",
"Lorem".getRandomString(300),
"",
""
),
Task(
4,
"FreePrompt",
null,
"12",
"",
"Give me some text 4",
"Lorem".getRandomString(300),
"",
""
),
Task(
5,
"FreePrompt",
null,
"12",
"",
"Give me some text 5",
"Lorem".getRandomString(300),
"",
""
),
Task(
6,
"FreePrompt",
null,
"12",
"",
"Give me some text 6",
"Lorem".getRandomString(300),
"",
""
),
Task(
7,
"FreePrompt",
null,
"12",
"",
"Give me some text 7",
"Lorem".getRandomString(300),
"",
""
)

Просмотреть файл

@ -0,0 +1,58 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.nextcloud.client.assistant.task
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.nextcloud.client.assistant.extensions.statusData
import com.owncloud.android.lib.resources.assistant.model.Task
@Composable
fun TaskStatus(task: Task, foregroundColor: Color) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp),
verticalAlignment = Alignment.CenterVertically
) {
val (iconId, descriptionId) = task.statusData()
Image(
painter = painterResource(id = iconId),
modifier = Modifier.size(16.dp),
colorFilter = ColorFilter.tint(foregroundColor),
contentDescription = "status icon"
)
Spacer(modifier = Modifier.width(6.dp))
Text(text = stringResource(id = descriptionId), color = foregroundColor)
/*
Spacer(modifier = Modifier.weight(1f))
Text(text = task.completionDateRepresentation(), color = foregroundColor)
Spacer(modifier = Modifier.width(6.dp))
*/
}
}

Просмотреть файл

@ -1,27 +1,22 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper_ozturk@proton.me>
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH
* SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.nextcloud.client.assistant.component
package com.nextcloud.client.assistant.task
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
@ -31,18 +26,15 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.nextcloud.client.assistant.extensions.statusData
import com.nextcloud.client.assistant.taskDetail.TaskDetailBottomSheet
import com.nextcloud.ui.composeComponents.bottomSheet.MoreActionsBottomSheet
import com.nextcloud.utils.extensions.getRandomString
import com.owncloud.android.R
import com.owncloud.android.lib.resources.assistant.model.Task
@ -53,7 +45,7 @@ fun TaskView(
task: Task,
showDeleteTaskAlertDialog: (Long) -> Unit
) {
var expanded by remember { mutableStateOf(false) }
var showTaskDetailBottomSheet by remember { mutableStateOf(false) }
var showMoreActionsBottomSheet by remember { mutableStateOf(false) }
Column(
@ -62,7 +54,7 @@ fun TaskView(
.clip(RoundedCornerShape(16.dp))
.background(MaterialTheme.colorScheme.primary)
.combinedClickable(onClick = {
expanded = !expanded
showTaskDetailBottomSheet = true
}, onLongClick = {
showMoreActionsBottomSheet = true
})
@ -84,10 +76,11 @@ fun TaskView(
HorizontalDivider(modifier = Modifier.padding(horizontal = 4.dp, vertical = 8.dp))
Text(
text = if (expanded) it else it.take(100) + "...",
text = it.take(100),
fontSize = 12.sp,
color = Color.White,
modifier = Modifier
.height(100.dp)
.animateContentSize(
animationSpec = spring(
dampingRatio = Spring.DampingRatioLowBouncy,
@ -97,39 +90,7 @@ fun TaskView(
)
}
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp),
verticalAlignment = Alignment.CenterVertically
) {
val (iconId, descriptionId) = task.statusData()
Image(
painter = painterResource(id = iconId),
modifier = Modifier.size(16.dp),
colorFilter = ColorFilter.tint(Color.White),
contentDescription = "status icon"
)
Spacer(modifier = Modifier.width(6.dp))
Text(text = stringResource(id = descriptionId), color = Color.White)
Spacer(modifier = Modifier.weight(1f))
if ((task.output?.length ?: 0) >= 100) {
Image(
painter = painterResource(
id = if (!expanded) R.drawable.ic_expand_more else R.drawable.ic_expand_less
),
contentDescription = "expand content icon",
colorFilter = ColorFilter.tint(Color.White)
)
}
Spacer(modifier = Modifier.width(8.dp))
}
TaskStatus(task, foregroundColor = Color.White)
if (showMoreActionsBottomSheet) {
val bottomSheetAction = listOf(
@ -147,27 +108,20 @@ fun TaskView(
dismiss = { showMoreActionsBottomSheet = false }
)
}
if (showTaskDetailBottomSheet) {
TaskDetailBottomSheet(task) {
showTaskDetailBottomSheet = false
}
}
}
}
@Suppress("MagicNumber")
@Preview
@Composable
private fun TaskViewPreview() {
val output =
"Lorem Ipsum is simply dummy text of the printing and " +
"typesetting industry. Lorem Ipsum has been the " +
"industry's standard dummy text ever since the 1500s, " +
"when an unknown printer took a galley of type and " +
"scrambled it to make a type specimen book. " +
"It has survived not only five centuries, but also " +
"the leap into electronic typesetting, remaining" +
" essentially unchanged. It wLorem Ipsum is simply dummy" +
" text of the printing and typesetting industry. " +
"Lorem Ipsum has been the industry's standard dummy " +
"text ever since the 1500s, when an unknown printer took a" +
" galley of type and scrambled it to make a type specimen book. " +
"It has survived not only five centuries, but also the leap " +
"into electronic typesetting, remaining essentially unchanged."
val output = "Lorem".getRandomString(100)
TaskView(
task = Task(

Просмотреть файл

@ -0,0 +1,165 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.nextcloud.client.assistant.taskDetail
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.nextcloud.client.assistant.task.TaskStatus
import com.nextcloud.utils.extensions.getRandomString
import com.owncloud.android.R
import com.owncloud.android.lib.resources.assistant.model.Task
@Suppress("LongMethod")
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class)
@Composable
fun TaskDetailBottomSheet(task: Task, dismiss: () -> Unit) {
var showInput by remember { mutableStateOf(true) }
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
ModalBottomSheet(
modifier = Modifier.padding(top = 32.dp),
containerColor = Color.White,
onDismissRequest = {
dismiss()
},
sheetState = sheetState
) {
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
) {
stickyHeader {
Row(
modifier = Modifier
.fillMaxWidth()
.background(color = colorResource(id = R.color.light_grey), shape = RoundedCornerShape(8.dp))
) {
TextInputSelectButton(
Modifier.weight(1f),
R.string.assistant_task_detail_screen_input_button_title,
showInput,
onClick = {
showInput = true
}
)
TextInputSelectButton(
Modifier.weight(1f),
R.string.assistant_task_detail_screen_output_button_title,
!showInput,
onClick = {
showInput = false
}
)
}
}
item {
Spacer(modifier = Modifier.height(16.dp))
Column(
modifier = Modifier
.fillMaxSize()
.background(color = colorResource(id = R.color.light_grey), shape = RoundedCornerShape(8.dp))
.padding(16.dp)
) {
Text(
text = if (showInput) {
task.input ?: ""
} else {
task.output ?: ""
},
fontSize = 12.sp,
color = Color.Black,
modifier = Modifier
.animateContentSize(
animationSpec = spring(
dampingRatio = Spring.DampingRatioLowBouncy,
stiffness = Spring.StiffnessLow
)
)
)
}
TaskStatus(task, foregroundColor = Color.Black)
Spacer(modifier = Modifier.height(32.dp))
}
}
}
}
@Composable
private fun TextInputSelectButton(modifier: Modifier, titleId: Int, highlightCondition: Boolean, onClick: () -> Unit) {
Button(
onClick = onClick,
shape = RoundedCornerShape(8.dp),
colors = if (highlightCondition) {
ButtonDefaults.buttonColors(containerColor = Color.White)
} else {
ButtonDefaults.buttonColors(containerColor = colorResource(id = R.color.light_grey))
},
modifier = modifier
.widthIn(min = 0.dp, max = 200.dp)
.padding(horizontal = 4.dp)
) {
Text(text = stringResource(id = titleId), color = Color.Black)
}
}
@Suppress("MagicNumber")
@Preview
@Composable
private fun TaskDetailScreenPreview() {
TaskDetailBottomSheet(
task = Task(
1,
"Free Prompt",
0,
"1",
"1",
"Give me text".getRandomString(100),
"output".getRandomString(300),
"",
""
)
) {
}
}

Просмотреть файл

@ -5,7 +5,7 @@
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.nextcloud.client.assistant.component
package com.nextcloud.client.assistant.taskTypes
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Row

Просмотреть файл

@ -36,7 +36,7 @@ import java.lang.ref.WeakReference
class ComposeActivity : DrawerActivity() {
lateinit var binding: ActivityComposeBinding
private var menuItemId: Int? = null
private var menuItemId: Int = R.id.nav_all_files
companion object {
const val DESTINATION = "DESTINATION"
@ -51,13 +51,12 @@ class ComposeActivity : DrawerActivity() {
val destination = intent.getSerializableArgument(DESTINATION, ComposeDestination::class.java)
val titleId = intent.getIntExtra(TITLE, R.string.empty)
menuItemId = intent.getIntExtra(MENU_ITEM, -1)
menuItemId = intent.getIntExtra(MENU_ITEM, R.id.nav_all_files)
setupToolbar()
updateActionBarTitleAndHomeButtonByString(getString(titleId))
setupDrawer(menuItemId)
if (menuItemId != -1) {
setupDrawer(menuItemId!!)
setupToolbarShowOnlyMenuButtonAndTitle(getString(titleId)) {
openDrawer()
}
binding.composeView.setContent {
@ -72,15 +71,13 @@ class ComposeActivity : DrawerActivity() {
override fun onResume() {
super.onResume()
if (menuItemId != -1) {
setDrawerMenuItemChecked(R.id.nav_assistant)
}
setDrawerMenuItemChecked(menuItemId)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
android.R.id.home -> {
if (isDrawerOpen) closeDrawer() else openDrawer()
toggleDrawer()
true
}
else -> super.onOptionsItemSelected(item)

Просмотреть файл

@ -0,0 +1,17 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.nextcloud.utils.extensions
fun String.getRandomString(length: Int): String {
val allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9')
val result = (1..length)
.map { allowedChars.random() }
.joinToString("")
return this + result
}

Просмотреть файл

@ -286,10 +286,10 @@ public abstract class DrawerActivity extends ToolbarActivity
public void updateHeader() {
int primaryColor = themeColorUtils.unchangedPrimaryColor(getAccount(), this);
boolean isClientBranded = getResources().getBoolean(R.bool.is_branded_client);
if (getAccount() != null &&
getCapabilities().getServerBackground() != null &&
!getResources().getBoolean(R.bool.is_branded_client)) {
getCapabilities().getServerBackground() != null && !isClientBranded) {
OCCapability capability = getCapabilities();
String logo = capability.getServerLogo();
@ -339,47 +339,57 @@ public abstract class DrawerActivity extends ToolbarActivity
}
// hide ecosystem apps according to user preference or in branded client
LinearLayout ecosystemApps = mNavigationViewHeader.findViewById(R.id.drawer_ecosystem_apps);
if (getResources().getBoolean(R.bool.is_branded_client) || !preferences.isShowEcosystemApps()) {
ecosystemApps.setVisibility(View.GONE);
LinearLayout banner = mNavigationViewHeader.findViewById(R.id.drawer_ecosystem_apps);
boolean shouldHideTopBanner = isClientBranded || !preferences.isShowEcosystemApps();
if (shouldHideTopBanner) {
hideTopBanner(banner);
} else {
LinearLayout notesView = ecosystemApps.findViewById(R.id.drawer_ecosystem_notes);
LinearLayout talkView = ecosystemApps.findViewById(R.id.drawer_ecosystem_talk);
LinearLayout moreView = ecosystemApps.findViewById(R.id.drawer_ecosystem_more);
LinearLayout assistantView = ecosystemApps.findViewById(R.id.drawer_ecosystem_assistant);
notesView.setOnClickListener(v -> openAppOrStore("it.niedermann.owncloud.notes"));
talkView.setOnClickListener(v -> openAppOrStore("com.nextcloud.talk2"));
moreView.setOnClickListener(v -> openAppStore("Nextcloud", true));
assistantView.setOnClickListener(v -> startComposeActivity(ComposeDestination.AssistantScreen, R.string.assistant_screen_top_bar_title, -1));
if (getCapabilities() != null && getCapabilities().getAssistant().isTrue()) {
assistantView.setVisibility(View.VISIBLE);
} else {
assistantView.setVisibility(View.GONE);
}
List<LinearLayout> views = Arrays.asList(notesView, talkView, moreView, assistantView);
int iconColor;
if (Hct.fromInt(primaryColor).getTone() < 80.0) {
iconColor = Color.WHITE;
} else {
iconColor = getColor(R.color.grey_800_transparent);
}
for (LinearLayout view : views) {
ImageView imageView = (ImageView) view.getChildAt(0);
imageView.setImageTintList(ColorStateList.valueOf(iconColor));
GradientDrawable background = (GradientDrawable) imageView.getBackground();
background.setStroke(DisplayUtils.convertDpToPixel(1, this), iconColor);
TextView textView = (TextView) view.getChildAt(1);
textView.setTextColor(iconColor);
}
ecosystemApps.setVisibility(View.VISIBLE);
showTopBanner(banner, primaryColor);
}
}
private void hideTopBanner(LinearLayout banner) {
banner.setVisibility(View.GONE);
}
private void showTopBanner(LinearLayout banner, int primaryColor) {
LinearLayout notesView = banner.findViewById(R.id.drawer_ecosystem_notes);
LinearLayout talkView = banner.findViewById(R.id.drawer_ecosystem_talk);
LinearLayout moreView = banner.findViewById(R.id.drawer_ecosystem_more);
LinearLayout assistantView = banner.findViewById(R.id.drawer_ecosystem_assistant);
notesView.setOnClickListener(v -> openAppOrStore("it.niedermann.owncloud.notes"));
talkView.setOnClickListener(v -> openAppOrStore("com.nextcloud.talk2"));
moreView.setOnClickListener(v -> openAppStore("Nextcloud", true));
assistantView.setOnClickListener(v -> startComposeActivity(ComposeDestination.AssistantScreen, R.string.assistant_screen_top_bar_title, -1));
if (getCapabilities() != null && getCapabilities().getAssistant().isTrue()) {
assistantView.setVisibility(View.VISIBLE);
} else {
assistantView.setVisibility(View.GONE);
}
List<LinearLayout> views = Arrays.asList(notesView, talkView, moreView, assistantView);
int iconColor;
if (Hct.fromInt(primaryColor).getTone() < 80.0) {
iconColor = Color.WHITE;
} else {
iconColor = getColor(R.color.grey_800_transparent);
}
for (LinearLayout view : views) {
ImageView imageView = (ImageView) view.getChildAt(0);
imageView.setImageTintList(ColorStateList.valueOf(iconColor));
GradientDrawable background = (GradientDrawable) imageView.getBackground();
background.setStroke(DisplayUtils.convertDpToPixel(1, this), iconColor);
TextView textView = (TextView) view.getChildAt(1);
textView.setTextColor(iconColor);
}
banner.setVisibility(View.VISIBLE);
}
/**
* Open specified app and, if not installed redirect to corresponding download.
*
@ -463,9 +473,7 @@ public abstract class DrawerActivity extends ToolbarActivity
DrawerMenuUtil.filterGroupfoldersMenuItem(menu, capability);
DrawerMenuUtil.filterAssistantMenuItem(menu, capability, getResources());
DrawerMenuUtil.setupHomeMenuItem(menu, getResources());
DrawerMenuUtil.removeMenuItem(menu, R.id.nav_community,
!getResources().getBoolean(R.bool.participate_enabled));
DrawerMenuUtil.removeMenuItem(menu, R.id.nav_community, !getResources().getBoolean(R.bool.participate_enabled));
DrawerMenuUtil.removeMenuItem(menu, R.id.nav_shared, !getResources().getBoolean(R.bool.shared_enabled));
DrawerMenuUtil.removeMenuItem(menu, R.id.nav_logout, !getResources().getBoolean(R.bool.show_drawer_logout));
}
@ -494,10 +502,17 @@ public abstract class DrawerActivity extends ToolbarActivity
MainApp.showOnlyPersonalFiles(itemId == R.id.nav_personal_files);
Intent intent = new Intent(getApplicationContext(), FileDisplayActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
if (this instanceof ComposeActivity) {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
}
intent.setAction(FileDisplayActivity.ALL_FILES);
intent.putExtra(FileDisplayActivity.DRAWER_MENU_ID, menuItem.getItemId());
startActivity(intent);
}
closeDrawer();
} else if (itemId == R.id.nav_favorites) {
handleSearchEvents(new SearchEvent("", SearchRemoteOperation.SearchType.FAVORITE_SEARCH),
menuItem.getItemId());
@ -520,7 +535,8 @@ public abstract class DrawerActivity extends ToolbarActivity
startActivity(CommunityActivity.class);
} else if (itemId == R.id.nav_logout) {
mCheckedMenuItem = -1;
menuItem.setChecked(false);
MenuItem isNewMenuItemChecked = menuItem.setChecked(false);
Log_OC.d(TAG,"onNavigationItemClicked nav_logout setChecked " + isNewMenuItemChecked);
final Optional<User> optionalUser = getUser();
if (optionalUser.isPresent()) {
UserInfoActivity.openAccountRemovalDialog(optionalUser.get(), getSupportFragmentManager());
@ -627,6 +643,11 @@ public abstract class DrawerActivity extends ToolbarActivity
private void launchActivityForSearch(SearchEvent searchEvent, int menuItemId) {
Intent intent = new Intent(getApplicationContext(), FileDisplayActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
if (this instanceof ComposeActivity) {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
}
intent.setAction(Intent.ACTION_SEARCH);
intent.putExtra(OCFileListFragment.SEARCH_EVENT, searchEvent);
intent.putExtra(FileDisplayActivity.DRAWER_MENU_ID, menuItemId);
@ -673,6 +694,14 @@ public abstract class DrawerActivity extends ToolbarActivity
return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(GravityCompat.START);
}
public void toggleDrawer() {
if (isDrawerOpen()) {
closeDrawer();
} else {
openDrawer();
}
}
/**
* closes the drawer.
*/
@ -1115,6 +1144,11 @@ public abstract class DrawerActivity extends ToolbarActivity
MainApp.showOnlyPersonalFiles(onlyPersonalFiles);
Intent fileDisplayActivity = new Intent(getApplicationContext(), FileDisplayActivity.class);
fileDisplayActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
if (this instanceof ComposeActivity) {
fileDisplayActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
}
fileDisplayActivity.setAction(FileDisplayActivity.ALL_FILES);
startActivity(fileDisplayActivity);
}
@ -1122,7 +1156,8 @@ public abstract class DrawerActivity extends ToolbarActivity
@Override
public void avatarGenerated(Drawable avatarDrawable, Object callContext) {
if (callContext instanceof MenuItem menuItem) {
menuItem.setIcon(avatarDrawable);
MenuItem newIcon = menuItem.setIcon(avatarDrawable);
Log_OC.d(TAG,"avatarGenerated new icon: " + newIcon);
} else if (callContext instanceof ImageView imageView) {
imageView.setImageDrawable(avatarDrawable);
} else if (callContext instanceof MaterialButton materialButton) {

Просмотреть файл

@ -104,6 +104,22 @@ public abstract class ToolbarActivity extends BaseActivity implements Injectable
viewThemeUtils.material.colorMaterialTextButton(mSwitchAccountButton);
}
public void setupToolbarShowOnlyMenuButtonAndTitle(String title, View.OnClickListener toggleDrawer) {
setupToolbar(false, false);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayShowTitleEnabled(false);
}
LinearLayout toolbar = findViewById(R.id.toolbar_linear_layout);
MaterialButton menuButton = findViewById(R.id.toolbar_menu_button);
MaterialTextView titleTextView = findViewById(R.id.toolbar_title);
titleTextView.setText(title);
toolbar.setVisibility(View.VISIBLE);
menuButton.setOnClickListener(toggleDrawer);
}
public void setupToolbar() {
setupToolbar(false, false);
}
@ -278,7 +294,7 @@ public abstract class ToolbarActivity extends BaseActivity implements Injectable
public void clearToolbarSubtitle() {
ActionBar actionBar = getSupportActionBar();
if(actionBar != null){
if (actionBar != null) {
actionBar.setSubtitle(null);
}
}

Просмотреть файл

@ -27,7 +27,7 @@ public final class DrawerMenuUtil {
User user,
Resources resources) {
if (user.isAnonymous()) {
filterMenuItems(menu, R.id.nav_gallery, R.id.nav_favorites);
removeMenuItem(menu, R.id.nav_gallery, R.id.nav_favorites);
}
if (!resources.getBoolean(R.bool.recently_modified_enabled)) {
@ -38,26 +38,29 @@ public final class DrawerMenuUtil {
public static void filterTrashbinMenuItem(Menu menu, @Nullable OCCapability capability) {
if (capability != null && capability.getFilesUndelete().isFalse() ||
capability != null && capability.getFilesUndelete().isUnknown()) {
filterMenuItems(menu, R.id.nav_trashbin);
removeMenuItem(menu, R.id.nav_trashbin);
}
}
public static void filterActivityMenuItem(Menu menu, @Nullable OCCapability capability) {
if (capability != null && capability.getActivity().isFalse()) {
filterMenuItems(menu, R.id.nav_activity);
removeMenuItem(menu, R.id.nav_activity);
}
}
public static void filterAssistantMenuItem(Menu menu, @Nullable OCCapability capability, Resources resources) {
boolean showCondition = capability != null && capability.getAssistant().isTrue() && !resources.getBoolean(R.bool.is_branded_client);
if (!showCondition) {
filterMenuItems(menu, R.id.nav_assistant);
if (resources.getBoolean(R.bool.is_branded_client)) {
if (capability != null && capability.getAssistant().isFalse()) {
removeMenuItem(menu, R.id.nav_assistant);
}
} else {
removeMenuItem(menu, R.id.nav_assistant);
}
}
public static void filterGroupfoldersMenuItem(Menu menu, @Nullable OCCapability capability) {
if (capability != null && !capability.getGroupfolders().isTrue()) {
filterMenuItems(menu, R.id.nav_groupfolders);
removeMenuItem(menu, R.id.nav_groupfolders);
}
}
@ -74,7 +77,7 @@ public final class DrawerMenuUtil {
}
}
private static void filterMenuItems(Menu menu, int... menuIds) {
private static void removeMenuItem(Menu menu, int... menuIds) {
if (menuIds != null) {
for (int menuId : menuIds) {
menu.removeItem(menuId);

Просмотреть файл

@ -1,15 +0,0 @@
<!--
~ Nextcloud - Android Client
~
~ SPDX-FileCopyrightText: 2018-2024 Google LLC
~ SPDX-License-Identifier: Apache-2.0
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="#FF000000"
android:pathData="m296,615 l-56,-56 240,-240 240,240 -56,56 -184,-184 -184,184Z" />
</vector>

Просмотреть файл

@ -114,6 +114,42 @@
</RelativeLayout>
<LinearLayout
android:id="@+id/toolbar_linear_layout"
android:visibility="gone"
tools:visibility="visible"
android:orientation="horizontal"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.button.MaterialButton
android:id="@+id/toolbar_menu_button"
style="@style/Widget.AppTheme.Button.IconButton"
android:layout_width="48dp"
android:layout_height="48dp"
app:cornerRadius="@dimen/button_corner_radius"
app:icon="@drawable/ic_menu"
app:iconTint="@color/black" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/toolbar_title"
android:gravity="center"
android:textColor="@color/black"
android:lines="1"
android:textSize="16sp"
android:layout_width="wrap_content"
android:layout_height="48dp"/>
</LinearLayout>
<!-- home/search toolbar -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/home_toolbar"

Просмотреть файл

@ -15,6 +15,7 @@
<color name="white">#ffffff</color>
<color name="white_helper_text">#B3FFFFFF</color>
<color name="text_color">#333333</color>
<color name="light_grey">#F5F5F5</color>
<color name="grid_file_features_icon_color">#303034</color>
<color name="grid_file_features_background_color">#E9E8EB</color>
<color name="drawer_text_color">@color/secondary_text_color</color>

Просмотреть файл

@ -52,6 +52,9 @@
<string name="assistant_screen_failed_task_text">Failed</string>
<string name="assistant_screen_running_task_text">In Progress</string>
<string name="assistant_task_detail_screen_input_button_title">Input</string>
<string name="assistant_task_detail_screen_output_button_title">Output</string>
<string name="assistant_screen_all_task_type">All</string>
<string name="drawer_item_assistant">Assistant</string>