diff --git a/drawable_resources/ic_star.svg b/drawable_resources/ic_star.svg new file mode 100644 index 0000000000..92c32ed1c6 --- /dev/null +++ b/drawable_resources/ic_star.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/drawable_resources/ic_star_outline.svg b/drawable_resources/ic_star_outline.svg new file mode 100644 index 0000000000..715b658805 --- /dev/null +++ b/drawable_resources/ic_star_outline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/drawable_resources/ic_tag.svg b/drawable_resources/ic_tag.svg new file mode 100644 index 0000000000..61c7eef956 --- /dev/null +++ b/drawable_resources/ic_tag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/java/com/owncloud/android/ui/adapter/FileDetailTabAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/FileDetailTabAdapter.java new file mode 100644 index 0000000000..8b71890d99 --- /dev/null +++ b/src/main/java/com/owncloud/android/ui/adapter/FileDetailTabAdapter.java @@ -0,0 +1,62 @@ +/* + * Nextcloud Android client application + * + * @author Andy Scherzinger + * Copyright (C) 2018 Andy Scherzinger + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or 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 . + */ + +package com.owncloud.android.ui.adapter; + +import android.accounts.Account; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentStatePagerAdapter; + +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.ui.fragment.FileDetailActivitiesFragment; +import com.owncloud.android.ui.fragment.FileDetailSharingFragment; + +/** + * File details pager adapter. + */ +public class FileDetailTabAdapter extends FragmentStatePagerAdapter { + private OCFile file; + private Account account; + + public FileDetailTabAdapter(FragmentManager fm, OCFile file, Account account) { + super(fm); + + this.file = file; + this.account = account; + } + + @Override + public Fragment getItem(int position) { + switch (position) { + case 0: + return FileDetailActivitiesFragment.newInstance(file, account); + case 1: + return FileDetailSharingFragment.newInstance(file, account); + default: + return null; + } + } + + @Override + public int getCount() { + return 2; + } +} diff --git a/src/main/java/com/owncloud/android/ui/fragment/FileDetailActivitiesFragment.java b/src/main/java/com/owncloud/android/ui/fragment/FileDetailActivitiesFragment.java new file mode 100644 index 0000000000..dde110dff5 --- /dev/null +++ b/src/main/java/com/owncloud/android/ui/fragment/FileDetailActivitiesFragment.java @@ -0,0 +1,76 @@ +/* + * Nextcloud Android client application + * + * @author Andy Scherzinger + * Copyright (C) 2018 Andy Scherzinger + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or 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 . + */ + +package com.owncloud.android.ui.fragment; + +import android.accounts.Account; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.owncloud.android.R; +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.ui.activity.FileActivity; + +public class FileDetailActivitiesFragment extends Fragment { + + private static final String ARG_FILE = "FILE"; + private static final String ARG_ACCOUNT = "ACCOUNT"; + + private OCFile file; + private Account account; + + public static FileDetailActivitiesFragment newInstance(OCFile file, Account account) { + FileDetailActivitiesFragment fragment = new FileDetailActivitiesFragment(); + Bundle args = new Bundle(); + args.putParcelable(ARG_FILE, file); + args.putParcelable(ARG_ACCOUNT, account); + fragment.setArguments(args); + return fragment; + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, + Bundle savedInstanceState) { + + file = getArguments().getParcelable(ARG_FILE); + account = getArguments().getParcelable(ARG_ACCOUNT); + + if (savedInstanceState != null) { + file = savedInstanceState.getParcelable(FileActivity.EXTRA_FILE); + account = savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT); + } + + View view = inflater.inflate(R.layout.file_details_activities_fragment, container, false); + + setupView(view); + + return view; + } + + private void setupView(View view) { + // TODO populate activities list + } +} diff --git a/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java b/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java index 168938d175..666905e8b5 100644 --- a/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java +++ b/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java @@ -25,6 +25,8 @@ import android.accounts.Account; import android.graphics.Bitmap; import android.os.Bundle; import android.support.design.widget.Snackbar; +import android.support.design.widget.TabLayout; +import android.support.v4.view.ViewPager; import android.support.v7.widget.SwitchCompat; import android.view.LayoutInflater; import android.view.Menu; @@ -53,6 +55,7 @@ import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.shares.OCShare; import com.owncloud.android.ui.activity.FileActivity; import com.owncloud.android.ui.activity.FileDisplayActivity; +import com.owncloud.android.ui.adapter.FileDetailTabAdapter; import com.owncloud.android.ui.adapter.UserListAdapter; import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment; import com.owncloud.android.ui.dialog.RenameFileDialogFragment; @@ -68,8 +71,7 @@ import java.util.ArrayList; /** * This Fragment is used to display the details about a file. */ -public class FileDetailFragment extends FileFragment implements OnClickListener, - CompoundButton.OnCheckedChangeListener { +public class FileDetailFragment extends FileFragment implements OnClickListener { private int mLayout; private View mView; @@ -154,13 +156,11 @@ public class FileDetailFragment extends FileFragment implements OnClickListener, if (mLayout == R.layout.file_details_fragment) { int accentColor = ThemeUtils.primaryAccentColor(getContext()); - SwitchCompat favoriteToggle = mView.findViewById(R.id.fdFavorite); - favoriteToggle.setOnCheckedChangeListener(this); - ThemeUtils.tintSwitch(favoriteToggle, accentColor, false); ProgressBar progressBar = mView.findViewById(R.id.fdProgressBar); ThemeUtils.colorHorizontalProgressBar(progressBar, ThemeUtils.primaryAccentColor(getContext())); mProgressListener = new ProgressListener(progressBar); mView.findViewById(R.id.fdCancelBtn).setOnClickListener(this); + mView.findViewById(R.id.fdFavorite).setOnClickListener(this); ((TextView)mView.findViewById(R.id.fdShareTitle)).setTextColor(accentColor); ((TextView)mView.findViewById(R.id.fdShareWithUsersTitle)).setTextColor(accentColor); } @@ -169,6 +169,38 @@ public class FileDetailFragment extends FileFragment implements OnClickListener, return mView; } + private void setupViewPager(View view) { + TabLayout tabLayout = view.findViewById(R.id.tab_layout); + tabLayout.removeAllTabs(); + + tabLayout.addTab(tabLayout.newTab().setText(R.string.drawer_item_activities)); + tabLayout.addTab(tabLayout.newTab().setText(R.string.share_dialog_title)); + + tabLayout.setTabGravity(TabLayout.GRAVITY_FILL); + + final ViewPager viewPager = view.findViewById(R.id.pager); + final FileDetailTabAdapter adapter = new FileDetailTabAdapter + (getFragmentManager(), getFile(),mAccount); + viewPager.setAdapter(adapter); + viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout)); + tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { + @Override + public void onTabSelected(TabLayout.Tab tab) { + viewPager.setCurrentItem(tab.getPosition()); + } + + @Override + public void onTabUnselected(TabLayout.Tab tab) { + + } + + @Override + public void onTabReselected(TabLayout.Tab tab) { + + } + }); + } + @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); @@ -359,18 +391,26 @@ public class FileDetailFragment extends FileFragment implements OnClickListener, ((FileDisplayActivity) mContainerActivity).cancelTransference(getFile()); break; } + case R.id.fdFavorite: { + if (getFile().isAvailableOffline()) { + ((ImageView)getView().findViewById(R.id.fdFavorite)). + setImageDrawable(getResources() + .getDrawable(R.drawable.ic_star_outline)); + } else { + ((ImageView)getView().findViewById(R.id.fdFavorite)) + .setImageDrawable(getResources() + .getDrawable(R.drawable.ic_star)); + } + mContainerActivity.getFileOperationsHelper() + .toggleOfflineFile(getFile(), !getFile().isAvailableOffline()); + break; + } default: Log_OC.e(TAG, "Incorrect view clicked!"); break; } } - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - SwitchCompat favSwitch = getView().findViewById(R.id.fdFavorite); - mContainerActivity.getFileOperationsHelper().toggleOfflineFile(getFile(), favSwitch.isChecked()); - } - /** * Check if the fragment was created with an empty layout. An empty fragment can't show file details, must be replaced. * @@ -419,15 +459,13 @@ public class FileDetailFragment extends FileFragment implements OnClickListener, setFilename(file.getFileName()); setFiletype(file); setFilesize(file.getFileLength()); - setTimeModified(file.getModificationTimestamp()); - SwitchCompat favSwitch = getView().findViewById(R.id.fdFavorite); - favSwitch.setChecked(file.isAvailableOffline()); - - setShareByLinkInfo(file.isSharedViaLink()); - - setShareWithUserInfo(); + if (file.isAvailableOffline()) { + ((ImageView)getView().findViewById(R.id.fdFavorite)).setImageDrawable(getResources().getDrawable(R.drawable.ic_star)); + } else { + ((ImageView)getView().findViewById(R.id.fdFavorite)).setImageDrawable(getResources().getDrawable(R.drawable.ic_star_outline)); + } // configure UI for depending upon local state of the file FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder(); @@ -448,6 +486,9 @@ public class FileDetailFragment extends FileFragment implements OnClickListener, setButtonsForRemote(); } } + + setupViewPager(getView()); + getView().invalidate(); } @@ -634,9 +675,6 @@ public class FileDetailFragment extends FileFragment implements OnClickListener, */ private void setButtonsForTransferring() { if (!isEmpty()) { - // let's protect the user from himself ;) - getView().findViewById(R.id.fdFavorite).setEnabled(false); - // show the progress bar for the transfer getView().findViewById(R.id.fdProgressBlock).setVisibility(View.VISIBLE); TextView progressText = getView().findViewById(R.id.fdProgressText); @@ -660,8 +698,6 @@ public class FileDetailFragment extends FileFragment implements OnClickListener, */ private void setButtonsForDown() { if (!isEmpty()) { - getView().findViewById(R.id.fdFavorite).setEnabled(true); - // hides the progress bar getView().findViewById(R.id.fdProgressBlock).setVisibility(View.GONE); TextView progressText = getView().findViewById(R.id.fdProgressText); @@ -674,8 +710,6 @@ public class FileDetailFragment extends FileFragment implements OnClickListener, */ private void setButtonsForRemote() { if (!isEmpty()) { - getView().findViewById(R.id.fdFavorite).setEnabled(true); - // hides the progress bar getView().findViewById(R.id.fdProgressBlock).setVisibility(View.GONE); TextView progressText = getView().findViewById(R.id.fdProgressText); diff --git a/src/main/java/com/owncloud/android/ui/fragment/FileDetailSharingFragment.java b/src/main/java/com/owncloud/android/ui/fragment/FileDetailSharingFragment.java new file mode 100644 index 0000000000..f3cc8d7908 --- /dev/null +++ b/src/main/java/com/owncloud/android/ui/fragment/FileDetailSharingFragment.java @@ -0,0 +1,175 @@ +/* + * Nextcloud Android client application + * + * @author Andy Scherzinger + * Copyright (C) 2018 Andy Scherzinger + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or 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 . + */ + +package com.owncloud.android.ui.fragment; + +import android.accounts.Account; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.ListAdapter; +import android.widget.ListView; +import android.widget.TextView; + +import com.owncloud.android.R; +import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.lib.resources.shares.OCShare; +import com.owncloud.android.ui.activity.FileActivity; +import com.owncloud.android.ui.adapter.UserListAdapter; + +import java.util.ArrayList; + +public class FileDetailSharingFragment extends Fragment { + + private static final String ARG_FILE = "FILE"; + private static final String ARG_ACCOUNT = "ACCOUNT"; + + // to show share with users/groups info + private ArrayList mShares; + + private OCFile file; + private Account account; + + public static FileDetailSharingFragment newInstance(OCFile file, Account account) { + FileDetailSharingFragment fragment = new FileDetailSharingFragment(); + Bundle args = new Bundle(); + args.putParcelable(ARG_FILE, file); + args.putParcelable(ARG_ACCOUNT, account); + fragment.setArguments(args); + return fragment; + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, + Bundle savedInstanceState) { + + file = getArguments().getParcelable(ARG_FILE); + account = getArguments().getParcelable(ARG_ACCOUNT); + + if (savedInstanceState != null) { + file = savedInstanceState.getParcelable(FileActivity.EXTRA_FILE); + account = savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT); + } + + View view = inflater.inflate(R.layout.file_details_sharing_fragment, container, false); + + setupView(view); + + return view; + } + + private void setupView(View view) { + // TODO populate sharing UI + + setShareByLinkInfo(file.isSharedViaLink(), view); + + setShareWithUserInfo(view); + } + + /** + * Updates Share by link data + * + * @param isShareByLink flag is share by link is enable + */ + private void setShareByLinkInfo(boolean isShareByLink, View view) { + TextView tv = view.findViewById(R.id.fdSharebyLink); + if (tv != null) { + tv.setText(isShareByLink ? R.string.filedetails_share_link_enable : + R.string.filedetails_share_link_disable); + } + ImageView linkIcon = view.findViewById(R.id.fdShareLinkIcon); + if (linkIcon != null) { + linkIcon.setVisibility(isShareByLink ? View.VISIBLE : View.GONE); + } + } + + /** + * Update Share With data + */ + private void setShareWithUserInfo(View view){ + // Get Users and Groups + if (((FileActivity) getActivity()).getStorageManager() != null) { + FileDataStorageManager fileDataStorageManager = ((FileActivity) getActivity()).getStorageManager(); + mShares = fileDataStorageManager.getSharesWithForAFile( + file.getRemotePath(),account.name + ); + + // Update list of users/groups + updateListOfUserGroups(view); + } + } + + private void updateListOfUserGroups(View view) { + // Update list of users/groups + // TODO Refactoring: create a new {@link ShareUserListAdapter} instance with every call should not be needed + UserListAdapter mUserGroupsAdapter = new UserListAdapter( + getActivity().getApplicationContext(), + R.layout.share_user_item, mShares + ); + + // Show data + ListView usersList = view.findViewById(R.id.fdshareUsersList); + + // No data + TextView noList = view.findViewById(R.id.fdShareNoUsers); + + if (mShares.size() > 0) { + usersList.setVisibility(View.VISIBLE); + usersList.setAdapter(mUserGroupsAdapter); + noList.setVisibility(View.GONE); + setListViewHeightBasedOnChildren(usersList); + + } else { + usersList.setVisibility(View.GONE); + noList.setVisibility(View.VISIBLE); + } + } + + /** + * Fix scroll in listview when the parent is a ScrollView + */ + private static void setListViewHeightBasedOnChildren(ListView listView) { + ListAdapter listAdapter = listView.getAdapter(); + if (listAdapter == null) { + return; + } + int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(), View.MeasureSpec.AT_MOST); + int totalHeight = 0; + View view = null; + for (int i = 0; i < listAdapter.getCount(); i++) { + view = listAdapter.getView(i, view, listView); + if (i == 0) { + view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, ViewGroup.LayoutParams.WRAP_CONTENT)); + } + view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED); + totalHeight += view.getMeasuredHeight(); + } + ViewGroup.LayoutParams params = listView.getLayoutParams(); + params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); + listView.setLayoutParams(params); + listView.requestLayout(); + } +} diff --git a/src/main/res/drawable/ic_star.xml b/src/main/res/drawable/ic_star.xml new file mode 100644 index 0000000000..c8f9664af7 --- /dev/null +++ b/src/main/res/drawable/ic_star.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/src/main/res/drawable/ic_star_outline.xml b/src/main/res/drawable/ic_star_outline.xml new file mode 100644 index 0000000000..cb5739cc33 --- /dev/null +++ b/src/main/res/drawable/ic_star_outline.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/src/main/res/drawable/ic_tag.xml b/src/main/res/drawable/ic_tag.xml new file mode 100644 index 0000000000..80a4f0f50d --- /dev/null +++ b/src/main/res/drawable/ic_tag.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/src/main/res/layout/file_details_activities_fragment.xml b/src/main/res/layout/file_details_activities_fragment.xml new file mode 100644 index 0000000000..0156bf6089 --- /dev/null +++ b/src/main/res/layout/file_details_activities_fragment.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/res/layout/file_details_fragment.xml b/src/main/res/layout/file_details_fragment.xml index 6d191433ad..39854c05ee 100644 --- a/src/main/res/layout/file_details_fragment.xml +++ b/src/main/res/layout/file_details_fragment.xml @@ -29,110 +29,99 @@ android:layout_height="wrap_content" android:orientation="vertical"> - - - - - - - - - - - - - - - - - - - - - + android:layout_margin="@dimen/standard_margin" + android:contentDescription="@string/file_icon" + android:src="@drawable/file" /> + android:background="@color/list_divider_background" /> - + android:layout_margin="@dimen/standard_margin" + android:orientation="vertical"> - + android:text="@string/placeholder_filename" + android:textSize="16sp" + android:textColor="@color/black"/> + + + + + + + + + + + + + + + + + android:text="@string/downloader_download_in_progress_ticker" /> + android:indeterminateOnly="false" /> + android:src="@drawable/ic_cancel" /> - + + android:background="@color/list_divider_background" /> + + + + + android:orientation="vertical" + android:visibility="gone"> + android:textColor="@color/color_accent" /> + android:visibility="gone" /> + android:text="@string/filedetails_share_link_disable" /> + android:textColor="@color/color_accent" /> + android:visibility="gone" /> + android:textSize="@dimen/share_no_users_text_size" /> diff --git a/src/main/res/layout/file_details_sharing_fragment.xml b/src/main/res/layout/file_details_sharing_fragment.xml new file mode 100644 index 0000000000..9d512b1e5d --- /dev/null +++ b/src/main/res/layout/file_details_sharing_fragment.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 5dfffd02f6..e75e4de43c 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -784,4 +784,5 @@ Upload content from other apps Create new folder Virus detected. Upload cannot be completed! + Tags