diff --git a/drawable_resources/ic_star.svg b/drawable_resources/ic_star.svg
new file mode 100644
index 000000000000..92c32ed1c617
--- /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 000000000000..715b6588058b
--- /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 000000000000..61c7eef9563f
--- /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 000000000000..8b71890d99e3
--- /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 000000000000..dde110dff5a9
--- /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 168938d175e8..666905e8b5ed 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.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.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 @@
/**
* 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 View onCreateView(LayoutInflater inflater, ViewGroup container,
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 View onCreateView(LayoutInflater inflater, ViewGroup container,
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 void onClick(View v) {
((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 void updateFileDetails(boolean transferring, boolean refresh) {
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 void updateFileDetails(boolean transferring, boolean refresh) {
setButtonsForRemote();
}
}
+
+ setupViewPager(getView());
+
getView().invalidate();
}
@@ -634,9 +675,6 @@ private static void setListViewHeightBasedOnChildren(ListView listView) {
*/
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 @@ private void setButtonsForTransferring() {
*/
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 @@ private void setButtonsForDown() {
*/
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 000000000000..f3cc8d7908ce
--- /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 000000000000..c8f9664af7c6
--- /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 000000000000..cb5739cc333c
--- /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 000000000000..80a4f0f50db2
--- /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 000000000000..0156bf608934
--- /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 6d191433ade0..39854c05ee7c 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:orientation="vertical">
-
+ android:text="@string/placeholder_filename"
+ android:textSize="16sp"
+ android:textColor="@color/black"/>
+ android:gravity="center"
+ android:orientation="horizontal">
+
+
+ android:text="@string/placeholder_fileSize"
+ android:textSize="16sp" />
-
+ android:gravity="end"
+ android:paddingEnd="@dimen/standard_quarter_padding"
+ android:paddingLeft="@dimen/zero"
+ android:paddingRight="@dimen/standard_quarter_padding"
+ android:paddingStart="@dimen/zero"
+ android:text="@string/info_separator"
+ android:textColor="@color/list_item_lastmod_and_filesize_text"
+ android:textSize="@dimen/two_line_secondary_text_size" />
-
+
-
-
-
+
-
+
-
-
-
-
-
-
-
-
+ 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 000000000000..9d512b1e5d34
--- /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 5dfffd02f699..e75e4de43c2e 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